ts-fortress 2.2.1 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +135 -0
  2. package/dist/array/array-of-length.d.mts.map +1 -1
  3. package/dist/array/array-of-length.mjs +8 -6
  4. package/dist/array/array-of-length.mjs.map +1 -1
  5. package/dist/array/array.d.mts.map +1 -1
  6. package/dist/array/array.mjs +8 -6
  7. package/dist/array/array.mjs.map +1 -1
  8. package/dist/array/non-empty-array.d.mts.map +1 -1
  9. package/dist/array/non-empty-array.mjs +8 -6
  10. package/dist/array/non-empty-array.mjs.map +1 -1
  11. package/dist/array/tuple.d.mts.map +1 -1
  12. package/dist/array/tuple.mjs +8 -6
  13. package/dist/array/tuple.mjs.map +1 -1
  14. package/dist/compose/intersection.d.mts.map +1 -1
  15. package/dist/compose/intersection.mjs +10 -10
  16. package/dist/compose/intersection.mjs.map +1 -1
  17. package/dist/compose/merge-records.d.mts.map +1 -1
  18. package/dist/compose/merge-records.mjs +10 -10
  19. package/dist/compose/merge-records.mjs.map +1 -1
  20. package/dist/compose/union.d.mts.map +1 -1
  21. package/dist/compose/union.mjs.map +1 -1
  22. package/dist/enum/enum.d.mts.map +1 -1
  23. package/dist/enum/enum.mjs.map +1 -1
  24. package/dist/enum/uint-range.d.mts.map +1 -1
  25. package/dist/enum/uint-range.mjs.map +1 -1
  26. package/dist/index.d.mts +0 -1
  27. package/dist/index.d.mts.map +1 -1
  28. package/dist/index.mjs +1 -1
  29. package/dist/record/key-value-record.d.mts.map +1 -1
  30. package/dist/record/key-value-record.mjs +21 -24
  31. package/dist/record/key-value-record.mjs.map +1 -1
  32. package/dist/record/omit.d.mts.map +1 -1
  33. package/dist/record/omit.mjs +3 -2
  34. package/dist/record/omit.mjs.map +1 -1
  35. package/dist/record/partial.d.mts.map +1 -1
  36. package/dist/record/partial.mjs +2 -2
  37. package/dist/record/partial.mjs.map +1 -1
  38. package/dist/record/pick.d.mts.map +1 -1
  39. package/dist/record/pick.mjs +2 -2
  40. package/dist/record/pick.mjs.map +1 -1
  41. package/dist/record/record.d.mts.map +1 -1
  42. package/dist/record/record.mjs +23 -21
  43. package/dist/record/record.mjs.map +1 -1
  44. package/dist/type.d.mts +1 -1
  45. package/dist/type.d.mts.map +1 -1
  46. package/dist/utils/create-assert-fn.mjs +1 -1
  47. package/dist/utils/create-cast-fn.mjs +1 -1
  48. package/dist/utils/create-primitive-type.mjs +1 -1
  49. package/dist/utils/index.d.mts +1 -0
  50. package/dist/utils/index.d.mts.map +1 -1
  51. package/dist/utils/index.mjs +1 -0
  52. package/dist/utils/index.mjs.map +1 -1
  53. package/dist/utils/validation-error.d.mts.map +1 -0
  54. package/dist/utils/validation-error.mjs.map +1 -0
  55. package/package.json +4 -2
  56. package/src/array/array-of-length.mts +12 -7
  57. package/src/array/array-of-length.test.mts +10 -1
  58. package/src/array/array.mts +12 -7
  59. package/src/array/array.test.mts +10 -1
  60. package/src/array/non-empty-array.mts +11 -7
  61. package/src/array/non-empty-array.test.mts +10 -1
  62. package/src/array/tuple.mts +11 -9
  63. package/src/array/tuple.test.mts +14 -1
  64. package/src/branded/brand.mts +2 -2
  65. package/src/branded/number/finite-number.test.mts +10 -1
  66. package/src/branded/number/int.test.mts +10 -1
  67. package/src/branded/number/int16.test.mts +10 -1
  68. package/src/branded/number/int32.test.mts +10 -1
  69. package/src/branded/number/non-negative-finite-number.test.mts +10 -1
  70. package/src/branded/number/non-zero-finite-number.test.mts +10 -1
  71. package/src/branded/number/non-zero-int.test.mts +10 -1
  72. package/src/branded/number/non-zero-safe-int.test.mts +10 -1
  73. package/src/branded/number/positive-finite-number.test.mts +10 -1
  74. package/src/branded/number/positive-int.test.mts +10 -1
  75. package/src/branded/number/positive-safe-int.test.mts +10 -1
  76. package/src/branded/number/safe-int.test.mts +10 -1
  77. package/src/branded/number/safe-uint.test.mts +10 -1
  78. package/src/branded/number/uint.test.mts +10 -1
  79. package/src/branded/number/uint16.test.mts +10 -1
  80. package/src/branded/number/uint32.test.mts +10 -1
  81. package/src/branded/simple-branded-number.test.mts +19 -1
  82. package/src/branded/simple-branded-string.test.mts +19 -1
  83. package/src/compose/intersection.mts +23 -19
  84. package/src/compose/intersection.test.mts +28 -1
  85. package/src/compose/merge-records.mts +22 -19
  86. package/src/compose/merge-records.test.mts +10 -1
  87. package/src/compose/union.mts +6 -2
  88. package/src/compose/union.test.mts +10 -1
  89. package/src/enum/enum.mts +6 -2
  90. package/src/enum/enum.test.mts +10 -1
  91. package/src/enum/uint-range.mts +6 -2
  92. package/src/enum/uint-range.test.mts +10 -1
  93. package/src/index.mts +0 -1
  94. package/src/primitives/bigint.test.mts +19 -1
  95. package/src/primitives/boolean.test.mts +28 -1
  96. package/src/primitives/null.test.mts +9 -0
  97. package/src/primitives/number.test.mts +18 -0
  98. package/src/primitives/string.test.mts +18 -0
  99. package/src/primitives/symbol.test.mts +10 -1
  100. package/src/primitives/undefined.test.mts +9 -0
  101. package/src/record/key-value-record.mts +34 -36
  102. package/src/record/key-value-record.test.mts +14 -1
  103. package/src/record/keyof.test.mts +10 -1
  104. package/src/record/omit.mts +8 -5
  105. package/src/record/omit.test.mts +46 -1
  106. package/src/record/partial.mts +7 -5
  107. package/src/record/partial.test.mts +71 -1
  108. package/src/record/pick.mts +7 -5
  109. package/src/record/pick.test.mts +46 -1
  110. package/src/record/record-allow-excess-properties.test.mts +28 -1
  111. package/src/record/record-strict-composition-simple.test.mts +38 -0
  112. package/src/record/record-strict-composition.test.mts +71 -0
  113. package/src/record/record.mts +30 -29
  114. package/src/record/record.test.mts +26 -1
  115. package/src/record/strict-record.test.mts +10 -1
  116. package/src/type.mts +1 -1
  117. package/src/utils/create-assert-fn.mts +1 -1
  118. package/src/utils/create-cast-fn.mts +1 -1
  119. package/src/utils/create-primitive-type.mts +1 -1
  120. package/src/utils/index.mts +1 -0
  121. package/dist/validation-error.d.mts.map +0 -1
  122. package/dist/validation-error.mjs.map +0 -1
  123. package/src/combination.test.mts +0 -544
  124. /package/dist/{validation-error.d.mts → utils/validation-error.d.mts} +0 -0
  125. /package/dist/{validation-error.mjs → utils/validation-error.mjs} +0 -0
  126. /package/src/{validation-error.mts → utils/validation-error.mts} +0 -0
  127. /package/src/{validation-error.test.mts → utils/validation-error.test.mts} +0 -0
package/src/enum/enum.mts CHANGED
@@ -1,7 +1,11 @@
1
1
  import { ISet, Result } from 'ts-data-forge';
2
2
  import { type Type } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
- import { type ValidationErrorWithMessage } from '../validation-error.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ type ValidationErrorWithMessage,
8
+ } from '../utils/index.mjs';
5
9
 
6
10
  export const enumType = <const Values extends NonEmptyArray<Primitive>>(
7
11
  values: Values,
@@ -3,7 +3,7 @@ import { type TypeOf } from '../type.mjs';
3
3
  import {
4
4
  type ValidationError,
5
5
  validationErrorsToMessages,
6
- } from '../validation-error.mjs';
6
+ } from '../utils/index.mjs';
7
7
  import { enumType } from './enum.mjs';
8
8
 
9
9
  describe('enumType', () => {
@@ -76,6 +76,15 @@ describe('enumType', () => {
76
76
  throw new Error('Expected validation to fail');
77
77
  }
78
78
  });
79
+
80
+ test('validate returns input as-is for OK cases', () => {
81
+ const input = 'a';
82
+ const result = targetType.validate(input);
83
+ expect(Result.isOk(result)).toBe(true);
84
+ if (Result.isOk(result)) {
85
+ expect(result.value).toBe(input); // ✅ same reference
86
+ }
87
+ });
79
88
  });
80
89
 
81
90
  describe('fill', () => {
@@ -1,7 +1,11 @@
1
1
  import { isNumber, Num, Result } from 'ts-data-forge';
2
2
  import { type Type } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
- import { type ValidationErrorWithMessage } from '../validation-error.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ type ValidationErrorWithMessage,
8
+ } from '../utils/index.mjs';
5
9
 
6
10
  export const uintRange = <
7
11
  Start extends Uint8,
@@ -3,7 +3,7 @@ import { type TypeOf } from '../type.mjs';
3
3
  import {
4
4
  type ValidationError,
5
5
  validationErrorsToMessages,
6
- } from '../validation-error.mjs';
6
+ } from '../utils/index.mjs';
7
7
  import { uintRange } from './uint-range.mjs';
8
8
 
9
9
  describe('uintRange', () => {
@@ -57,6 +57,15 @@ describe('uintRange', () => {
57
57
  }
58
58
  });
59
59
 
60
+ test('validate returns input as-is for OK cases', () => {
61
+ const input = 5;
62
+ const result = month.validate(input);
63
+ expect(Result.isOk(result)).toBe(true);
64
+ if (Result.isOk(result)) {
65
+ expect(result.value).toBe(input); // ✅ same reference
66
+ }
67
+ });
68
+
60
69
  test('falsy case', () => {
61
70
  const result = month.validate(13);
62
71
  expect(Result.isErr(result)).toBe(true);
package/src/index.mts CHANGED
@@ -7,4 +7,3 @@ export * from './record/index.mjs';
7
7
  export * from './type.mjs';
8
8
  export * from './unknown.mjs';
9
9
  export * from './utils/index.mjs';
10
- export * from './validation-error.mjs';
@@ -1,6 +1,6 @@
1
1
  import { expectType, Result } from 'ts-data-forge';
2
2
  import { type TypeOf } from '../type.mjs';
3
- import { validationErrorsToMessages } from '../validation-error.mjs';
3
+ import { validationErrorsToMessages } from '../utils/index.mjs';
4
4
  import { bigint, bigintLiteral } from './bigint.mjs';
5
5
 
6
6
  describe('bigint', () => {
@@ -68,6 +68,15 @@ describe('bigint', () => {
68
68
  ]);
69
69
  }
70
70
  });
71
+
72
+ test('validate returns input as-is for OK cases', () => {
73
+ const input = 999n;
74
+ const result = targetType.validate(input);
75
+ expect(Result.isOk(result)).toBe(true);
76
+ if (Result.isOk(result)) {
77
+ expect(result.value).toBe(input); // ✅ same reference
78
+ }
79
+ });
71
80
  });
72
81
 
73
82
  describe('assertIs', () => {
@@ -215,6 +224,15 @@ describe('bigintLiteral', () => {
215
224
  ]);
216
225
  }
217
226
  });
227
+
228
+ test('validate returns input as-is for OK cases', () => {
229
+ const input = 42n;
230
+ const result = targetType.validate(input);
231
+ expect(Result.isOk(result)).toBe(true);
232
+ if (Result.isOk(result)) {
233
+ expect(result.value).toBe(input); // ✅ same reference
234
+ }
235
+ });
218
236
  });
219
237
 
220
238
  describe('cast', () => {
@@ -1,6 +1,6 @@
1
1
  import { expectType, Result } from 'ts-data-forge';
2
2
  import { type TypeOf } from '../type.mjs';
3
- import { validationErrorsToMessages } from '../validation-error.mjs';
3
+ import { validationErrorsToMessages } from '../utils/index.mjs';
4
4
  import { boolean, booleanLiteral } from './boolean.mjs';
5
5
 
6
6
  describe('boolean', () => {
@@ -68,6 +68,15 @@ describe('boolean', () => {
68
68
  ]);
69
69
  }
70
70
  });
71
+
72
+ test('validate returns input as-is for OK cases', () => {
73
+ const input = false;
74
+ const result = targetType.validate(input);
75
+ expect(Result.isOk(result)).toBe(true);
76
+ if (Result.isOk(result)) {
77
+ expect(result.value).toBe(input); // ✅ same reference
78
+ }
79
+ });
71
80
  });
72
81
 
73
82
  describe('assertIs', () => {
@@ -218,6 +227,15 @@ describe('booleanLiteral', () => {
218
227
  ]);
219
228
  }
220
229
  });
230
+
231
+ test('validate returns input as-is for OK cases', () => {
232
+ const input = true;
233
+ const result = targetType.validate(input);
234
+ expect(Result.isOk(result)).toBe(true);
235
+ if (Result.isOk(result)) {
236
+ expect(result.value).toBe(input); // ✅ same reference
237
+ }
238
+ });
221
239
  });
222
240
 
223
241
  describe('cast', () => {
@@ -304,6 +322,15 @@ describe('booleanLiteral', () => {
304
322
  ]);
305
323
  }
306
324
  });
325
+
326
+ test('validate returns input as-is for OK cases', () => {
327
+ const input = false;
328
+ const result = targetType.validate(input);
329
+ expect(Result.isOk(result)).toBe(true);
330
+ if (Result.isOk(result)) {
331
+ expect(result.value).toBe(input); // ✅ same reference
332
+ }
333
+ });
307
334
  });
308
335
 
309
336
  describe('fill', () => {
@@ -166,5 +166,14 @@ describe('nullType', () => {
166
166
  ]);
167
167
  }
168
168
  });
169
+
170
+ test('validate returns input as-is for OK cases', () => {
171
+ const input = null;
172
+ const result = nullType.validate(input);
173
+ expect(Result.isOk(result)).toBe(true);
174
+ if (Result.isOk(result)) {
175
+ expect(result.value).toBe(input); // ✅ same reference
176
+ }
177
+ });
169
178
  });
170
179
  });
@@ -174,6 +174,15 @@ describe('number', () => {
174
174
  ]);
175
175
  }
176
176
  });
177
+
178
+ test('validate returns input as-is for OK cases', () => {
179
+ const input = 123.456;
180
+ const result = num.validate(input);
181
+ expect(Result.isOk(result)).toBe(true);
182
+ if (Result.isOk(result)) {
183
+ expect(result.value).toBe(input); // ✅ same reference
184
+ }
185
+ });
177
186
  });
178
187
  });
179
188
 
@@ -280,5 +289,14 @@ describe('numberLiteral', () => {
280
289
  ]);
281
290
  }
282
291
  });
292
+
293
+ test('validate returns input as-is for OK cases', () => {
294
+ const input = 42;
295
+ const result = literal42.validate(input);
296
+ expect(Result.isOk(result)).toBe(true);
297
+ if (Result.isOk(result)) {
298
+ expect(result.value).toBe(input); // ✅ same reference
299
+ }
300
+ });
283
301
  });
284
302
  });
@@ -187,6 +187,15 @@ describe('string', () => {
187
187
  ]);
188
188
  }
189
189
  });
190
+
191
+ test('validate returns input as-is for OK cases', () => {
192
+ const input = 'hello world';
193
+ const result = str.validate(input);
194
+ expect(Result.isOk(result)).toBe(true);
195
+ if (Result.isOk(result)) {
196
+ expect(result.value).toBe(input); // ✅ same reference
197
+ }
198
+ });
190
199
  });
191
200
  });
192
201
 
@@ -302,6 +311,15 @@ describe('stringLiteral', () => {
302
311
  ]);
303
312
  }
304
313
  });
314
+
315
+ test('validate returns input as-is for OK cases', () => {
316
+ const input = 'hello';
317
+ const result = hello.validate(input);
318
+ expect(Result.isOk(result)).toBe(true);
319
+ if (Result.isOk(result)) {
320
+ expect(result.value).toBe(input); // ✅ same reference
321
+ }
322
+ });
305
323
  });
306
324
 
307
325
  describe('cast', () => {
@@ -1,6 +1,6 @@
1
1
  import { expectType, Result } from 'ts-data-forge';
2
2
  import { type TypeOf } from '../type.mjs';
3
- import { validationErrorsToMessages } from '../validation-error.mjs';
3
+ import { validationErrorsToMessages } from '../utils/index.mjs';
4
4
  import { symbol } from './symbol.mjs';
5
5
 
6
6
  describe('symbol', () => {
@@ -70,6 +70,15 @@ describe('symbol', () => {
70
70
  ]);
71
71
  }
72
72
  });
73
+
74
+ test('validate returns input as-is for OK cases', () => {
75
+ const input = Symbol('my-symbol');
76
+ const result = targetType.validate(input);
77
+ expect(Result.isOk(result)).toBe(true);
78
+ if (Result.isOk(result)) {
79
+ expect(result.value).toBe(input); // ✅ same reference
80
+ }
81
+ });
73
82
  });
74
83
 
75
84
  describe('assertIs', () => {
@@ -175,5 +175,14 @@ describe('undefinedType', () => {
175
175
  ]);
176
176
  }
177
177
  });
178
+
179
+ test('validate returns input as-is for OK cases', () => {
180
+ const input = undefined;
181
+ const result = undefinedType.validate(input);
182
+ expect(Result.isOk(result)).toBe(true);
183
+ if (Result.isOk(result)) {
184
+ expect(result.value).toBe(input); // ✅ same reference
185
+ }
186
+ });
178
187
  });
179
188
  });
@@ -1,12 +1,14 @@
1
- import { isRecord, Result } from 'ts-data-forge';
1
+ import { Arr, isRecord, Result } from 'ts-data-forge';
2
2
  import { type Type, type TypeOf } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
3
  import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
5
7
  createPrimitiveValidationError,
6
8
  prependPathToValidationErrors,
7
9
  type ValidationError,
8
10
  type ValidationErrorWithMessage,
9
- } from '../validation-error.mjs';
11
+ } from '../utils/index.mjs';
10
12
 
11
13
  type RecordResultType<
12
14
  K extends Type<string>,
@@ -36,43 +38,39 @@ export const keyValueRecord = <K extends Type<string>, V extends Type<unknown>>(
36
38
  ]);
37
39
  }
38
40
 
39
- const errors: readonly ValidationError[] = Object.entries(a).flatMap(
40
- ([k, v]) => {
41
- const keyErrors = (() => {
41
+ const errors: readonly ValidationError[] = Arr.generate(function* () {
42
+ for (const [k, v] of Object.entries(a)) {
43
+ {
42
44
  const res = keyType.validate(k);
43
- return Result.isErr(res)
44
- ? [
45
- {
46
- path: [],
47
- actualValue: k,
48
- expectedType: typeName,
49
- message: `The key of the record is expected to be <${keyType.typeName}>`,
50
- typeName,
51
- } satisfies ValidationErrorWithMessage,
52
- ...res.value,
53
- ]
54
- : [];
55
- })();
56
45
 
57
- const valueErrors = (() => {
46
+ if (Result.isErr(res)) {
47
+ yield {
48
+ path: [],
49
+ actualValue: k,
50
+ expectedType: typeName,
51
+ message: `The key of the record is expected to be <${keyType.typeName}>`,
52
+ typeName,
53
+ } satisfies ValidationErrorWithMessage;
54
+
55
+ yield* res.value;
56
+ }
57
+ }
58
+ {
58
59
  const res = valueType.validate(v);
59
- return Result.isErr(res)
60
- ? [
61
- {
62
- path: [],
63
- actualValue: v,
64
- expectedType: typeName,
65
- message: `The value of the record is expected to be <${valueType.typeName}>`,
66
- typeName,
67
- } satisfies ValidationErrorWithMessage,
68
- ...prependPathToValidationErrors(res.value, k),
69
- ]
70
- : [];
71
- })();
60
+ if (Result.isErr(res)) {
61
+ yield {
62
+ path: [],
63
+ actualValue: v,
64
+ expectedType: typeName,
65
+ message: `The value of the record is expected to be <${valueType.typeName}>`,
66
+ typeName,
67
+ } satisfies ValidationErrorWithMessage;
72
68
 
73
- return [...keyErrors, ...valueErrors];
74
- },
75
- );
69
+ yield* prependPathToValidationErrors(res.value, k);
70
+ }
71
+ }
72
+ }
73
+ });
76
74
 
77
75
  if (errors.length > 0) {
78
76
  return Result.err(errors);
@@ -4,7 +4,7 @@ import { type TypeOf } from '../type.mjs';
4
4
  import {
5
5
  type ValidationError,
6
6
  validationErrorsToMessages,
7
- } from '../validation-error.mjs';
7
+ } from '../utils/index.mjs';
8
8
  import { keyValueRecord } from './key-value-record.mjs';
9
9
 
10
10
  describe('keyValueRecord', () => {
@@ -74,6 +74,19 @@ describe('keyValueRecord', () => {
74
74
  }
75
75
  });
76
76
 
77
+ test('validate returns input as-is for OK cases', () => {
78
+ const input: UnknownRecord = {
79
+ year: 2000,
80
+ month: 12,
81
+ date: 25,
82
+ };
83
+ const result = strNumRecord.validate(input);
84
+ expect(Result.isOk(result)).toBe(true);
85
+ if (Result.isOk(result)) {
86
+ expect(result.value).toBe(input); // ✅ same reference
87
+ }
88
+ });
89
+
77
90
  test('falsy case', () => {
78
91
  const x: UnknownRecord = {
79
92
  year: 2000,
@@ -1,7 +1,7 @@
1
1
  import { expectType, Result } from 'ts-data-forge';
2
2
  import { number } from '../primitives/index.mjs';
3
3
  import { type Type, type TypeOf } from '../type.mjs';
4
- import { validationErrorsToMessages } from '../validation-error.mjs';
4
+ import { validationErrorsToMessages } from '../utils/index.mjs';
5
5
  import { keyof } from './keyof.mjs';
6
6
  import { record } from './record.mjs';
7
7
 
@@ -61,6 +61,15 @@ describe('keyof', () => {
61
61
  }
62
62
  });
63
63
 
64
+ test('validate returns input as-is for OK cases', () => {
65
+ const input = 'year';
66
+ const result = ymdKey.validate(input);
67
+ expect(Result.isOk(result)).toBe(true);
68
+ if (Result.isOk(result)) {
69
+ expect(result.value).toBe(input); // ✅ same reference
70
+ }
71
+ });
72
+
64
73
  test('falsy case', () => {
65
74
  const x: unknown = 'minutes';
66
75
 
@@ -1,7 +1,11 @@
1
1
  import { expectType, isRecord, Obj, Result } from 'ts-data-forge';
2
2
  import { type Type, type TypeOf } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
- import { createPrimitiveValidationError } from '../validation-error.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ createPrimitiveValidationError,
8
+ } from '../utils/index.mjs';
5
9
 
6
10
  /** Creates a record type with keys omitted. */
7
11
  export const omit = <
@@ -43,9 +47,8 @@ export const omit = <
43
47
 
44
48
  const baseValidationResult = recordType.validate(objectFilled);
45
49
 
46
- return Result.map(baseValidationResult, Obj.omit(keysToOmit)) as ReturnType<
47
- Type<V>['validate']
48
- >;
50
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
51
+ return Result.map(baseValidationResult, () => a as V);
49
52
  };
50
53
 
51
54
  const fill: Type<V>['fill'] = (a) => Obj.omit(recordType.fill(a), keysToOmit);
@@ -1,7 +1,7 @@
1
1
  import { expectType, Result } from 'ts-data-forge';
2
2
  import { number } from '../primitives/index.mjs';
3
3
  import { type Type, type TypeOf } from '../type.mjs';
4
- import { validationErrorsToMessages } from '../validation-error.mjs';
4
+ import { validationErrorsToMessages } from '../utils/index.mjs';
5
5
  import { omit } from './omit.mjs';
6
6
  import { record } from './record.mjs';
7
7
 
@@ -73,6 +73,51 @@ describe('omit', () => {
73
73
  }
74
74
  });
75
75
 
76
+ test('validate returns input as-is for OK cases', () => {
77
+ const input: UnknownRecord = {
78
+ year: 2000,
79
+ month: 12,
80
+ };
81
+ const result = ym.validate(input);
82
+ expect(Result.isOk(result)).toBe(true);
83
+ if (Result.isOk(result)) {
84
+ expect(result.value).toBe(input); // ✅ same reference
85
+ }
86
+ });
87
+
88
+ test('truthy case with additional keys', () => {
89
+ const x: UnknownRecord = {
90
+ year: 2000,
91
+ month: 12,
92
+ aaa: 999,
93
+ };
94
+
95
+ const result = ym.validate(x);
96
+ expect(Result.isOk(result)).toBe(true);
97
+
98
+ if (Result.isOk(result)) {
99
+ expectType<typeof result.value, Ym>('=');
100
+ expect(result.value).toStrictEqual({
101
+ year: 2000,
102
+ month: 12,
103
+ aaa: 999,
104
+ });
105
+ }
106
+ });
107
+
108
+ test('validate returns input as-is for OK cases with additional keys', () => {
109
+ const input: UnknownRecord = {
110
+ year: 2000,
111
+ month: 12,
112
+ aaa: 999,
113
+ };
114
+ const result = ym.validate(input);
115
+ expect(Result.isOk(result)).toBe(true);
116
+ if (Result.isOk(result)) {
117
+ expect(result.value).toBe(input); // ✅ same reference
118
+ }
119
+ });
120
+
76
121
  test('falsy case', () => {
77
122
  const x: UnknownRecord = {
78
123
  year: 2000,
@@ -1,7 +1,11 @@
1
1
  import { expectType, ISet, isRecord, Obj, Result } from 'ts-data-forge';
2
2
  import { type Type, type TypeOf } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
- import { createPrimitiveValidationError } from '../validation-error.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ createPrimitiveValidationError,
8
+ } from '../utils/index.mjs';
5
9
 
6
10
  /**
7
11
  * Creates a Partial type. If keysToBeOptional is set, only those keys are
@@ -58,9 +62,7 @@ export const partial = <
58
62
  const validationResult = recordType.validate(objectFilled);
59
63
 
60
64
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
61
- return Result.map(validationResult, Obj.pick(Object.keys(a))) as ReturnType<
62
- Type<V>['validate']
63
- >;
65
+ return Result.map(validationResult, () => a as V);
64
66
  };
65
67
 
66
68
  const fill: Type<V>['fill'] = (a) => {
@@ -4,7 +4,7 @@ import { type Type, type TypeOf } from '../type.mjs';
4
4
  import {
5
5
  type ValidationError,
6
6
  validationErrorsToMessages,
7
- } from '../validation-error.mjs';
7
+ } from '../utils/index.mjs';
8
8
  import { optional } from './optional.mjs';
9
9
  import { partial } from './partial.mjs';
10
10
  import { record } from './record.mjs';
@@ -88,6 +88,19 @@ describe('partial', () => {
88
88
  }
89
89
  });
90
90
 
91
+ test('validate returns input as-is for OK cases', () => {
92
+ const input: UnknownRecord = {
93
+ year: 2000,
94
+ month: 12,
95
+ date: 25,
96
+ };
97
+ const result = ymd.validate(input);
98
+ expect(Result.isOk(result)).toBe(true);
99
+ if (Result.isOk(result)) {
100
+ expect(result.value).toBe(input); // ✅ same reference
101
+ }
102
+ });
103
+
91
104
  test('truthy case optional keys', () => {
92
105
  const x: UnknownRecord = {};
93
106
 
@@ -100,6 +113,51 @@ describe('partial', () => {
100
113
  }
101
114
  });
102
115
 
116
+ test('validate returns input as-is for empty object', () => {
117
+ const input: UnknownRecord = {};
118
+ const result = ymd.validate(input);
119
+ expect(Result.isOk(result)).toBe(true);
120
+ if (Result.isOk(result)) {
121
+ expect(result.value).toBe(input); // ✅ same reference
122
+ }
123
+ });
124
+
125
+ test('truthy case with additional keys', () => {
126
+ const x: UnknownRecord = {
127
+ year: 2000,
128
+ month: 12,
129
+ date: 25,
130
+ aaa: 999,
131
+ };
132
+
133
+ const result = ymd.validate(x);
134
+ expectType<typeof result, Result<Ymd, readonly ValidationError[]>>('=');
135
+ expect(Result.isOk(result)).toBe(true);
136
+
137
+ if (Result.isOk(result)) {
138
+ expect(result.value).toStrictEqual({
139
+ year: 2000,
140
+ month: 12,
141
+ date: 25,
142
+ aaa: 999,
143
+ });
144
+ }
145
+ });
146
+
147
+ test('validate returns input as-is for OK cases with additional keys', () => {
148
+ const input: UnknownRecord = {
149
+ year: 2000,
150
+ month: 12,
151
+ date: 25,
152
+ aaa: 999,
153
+ };
154
+ const result = ymd.validate(input);
155
+ expect(Result.isOk(result)).toBe(true);
156
+ if (Result.isOk(result)) {
157
+ expect(result.value).toBe(input); // ✅ same reference
158
+ }
159
+ });
160
+
103
161
  test('falsy case 1', () => {
104
162
  const x: UnknownRecord = {
105
163
  year: 2000,
@@ -287,6 +345,18 @@ describe('partial', () => {
287
345
  }
288
346
  });
289
347
 
348
+ test('partiallyPartialType validate returns input as-is for OK cases', () => {
349
+ const input: UnknownRecord = {
350
+ year: 2000,
351
+ month: 12,
352
+ };
353
+ const result = ymd.validate(input);
354
+ expect(Result.isOk(result)).toBe(true);
355
+ if (Result.isOk(result)) {
356
+ expect(result.value).toBe(input); // ✅ same reference
357
+ }
358
+ });
359
+
290
360
  test('falsy case', () => {
291
361
  const x: UnknownRecord = {
292
362
  year: 2000,
@@ -1,7 +1,11 @@
1
1
  import { expectType, isRecord, Obj, Result } from 'ts-data-forge';
2
2
  import { type Type, type TypeOf } from '../type.mjs';
3
- import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
- import { createPrimitiveValidationError } from '../validation-error.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ createPrimitiveValidationError,
8
+ } from '../utils/index.mjs';
5
9
 
6
10
  /** Creates a record type with keys picked. */
7
11
  export const pick = <
@@ -44,9 +48,7 @@ export const pick = <
44
48
  const baseValidationResult = recordType.validate(objectFilled);
45
49
 
46
50
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
47
- return Result.map(baseValidationResult, Obj.pick(keysToPick)) as ReturnType<
48
- Type<V>['validate']
49
- >;
51
+ return Result.map(baseValidationResult, () => a as V);
50
52
  };
51
53
 
52
54
  const fill: Type<V>['fill'] = (a) =>