ts-fortress 2.0.3 → 2.1.0
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.
- package/README.md +56 -1
- package/dist/record/partial.d.mts.map +1 -1
- package/dist/record/partial.mjs +2 -1
- package/dist/record/partial.mjs.map +1 -1
- package/dist/record/record.d.mts +2 -0
- package/dist/record/record.d.mts.map +1 -1
- package/dist/record/record.mjs +19 -3
- package/dist/record/record.mjs.map +1 -1
- package/package.json +1 -1
- package/src/array/array-of-length.test.mts +16 -1
- package/src/array/array.test.mts +16 -1
- package/src/array/non-empty-array.test.mts +16 -1
- package/src/array/tuple.test.mts +18 -1
- package/src/compose/intersection.test.mts +43 -1
- package/src/compose/merge-records.test.mts +16 -1
- package/src/compose/union.test.mts +16 -1
- package/src/enum/enum.test.mts +16 -1
- package/src/enum/uint-range.test.mts +14 -1
- package/src/primitives/null.test.mts +170 -0
- package/src/primitives/number.test.mts +284 -0
- package/src/primitives/string.test.mts +341 -0
- package/src/primitives/undefined.test.mts +179 -0
- package/src/record/key-value-record.test.mts +27 -1
- package/src/record/keyof.test.mts +12 -0
- package/src/record/partial.mts +5 -1
- package/src/record/partial.test.mts +54 -1
- package/src/record/record-allow-excess-properties.test.mts +180 -0
- package/src/record/record-strict-composition-simple.test.mts +134 -0
- package/src/record/record-strict-composition.test.mts +403 -0
- package/src/record/record.mts +52 -25
- package/src/record/record.test.mts +71 -1
package/README.md
CHANGED
|
@@ -541,6 +541,35 @@ const UserProfileType = t.record({
|
|
|
541
541
|
}),
|
|
542
542
|
),
|
|
543
543
|
});
|
|
544
|
+
|
|
545
|
+
// Strict validation (disallow excess properties)
|
|
546
|
+
const StrictUserType = t.record(
|
|
547
|
+
{
|
|
548
|
+
id: t.string(''),
|
|
549
|
+
name: t.string(''),
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
allowExcessProperties: false, // Reject any properties not defined in schema
|
|
553
|
+
},
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
// Permissive validation (allow excess properties) - this is the default
|
|
557
|
+
const PermissiveUserType = t.record(
|
|
558
|
+
{
|
|
559
|
+
id: t.string(''),
|
|
560
|
+
name: t.string(''),
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
allowExcessProperties: true, // Allow additional properties (default behavior)
|
|
564
|
+
},
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
// Example usage
|
|
568
|
+
const strictData = { id: '123', name: 'John', extra: 'not allowed' };
|
|
569
|
+
console.log(StrictUserType.is(strictData)); // false - 'extra' property causes rejection
|
|
570
|
+
|
|
571
|
+
const permissiveData = { id: '123', name: 'John', extra: 'allowed' };
|
|
572
|
+
console.log(PermissiveUserType.is(permissiveData)); // true - 'extra' property is allowed
|
|
544
573
|
```
|
|
545
574
|
|
|
546
575
|
### Branded Types
|
|
@@ -649,6 +678,31 @@ try {
|
|
|
649
678
|
} catch (error) {
|
|
650
679
|
console.error('Validation failed:', error.message);
|
|
651
680
|
}
|
|
681
|
+
|
|
682
|
+
// Excess property validation example
|
|
683
|
+
const StrictType = t.record(
|
|
684
|
+
{
|
|
685
|
+
name: t.string(''),
|
|
686
|
+
age: t.number(0),
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
allowExcessProperties: false,
|
|
690
|
+
},
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
const dataWithExcess = { name: 'John', age: 30, extra: 'not allowed' };
|
|
694
|
+
const strictResult = StrictType.validate(dataWithExcess);
|
|
695
|
+
|
|
696
|
+
if (Result.isErr(strictResult)) {
|
|
697
|
+
console.log(strictResult.value);
|
|
698
|
+
// [{
|
|
699
|
+
// path: ['extra'],
|
|
700
|
+
// actualValue: 'not allowed',
|
|
701
|
+
// expectedType: '{ name: string, age: number }',
|
|
702
|
+
// message: 'Excess property "extra" is not allowed',
|
|
703
|
+
// typeName: '{ name: string, age: number }'
|
|
704
|
+
// }]
|
|
705
|
+
}
|
|
652
706
|
```
|
|
653
707
|
|
|
654
708
|
### ValidationError Structure
|
|
@@ -684,7 +738,8 @@ type ValidationError = Readonly<{
|
|
|
684
738
|
|
|
685
739
|
### Objects
|
|
686
740
|
|
|
687
|
-
- `t.record(schema)` - Object validation
|
|
741
|
+
- `t.record(schema, options?)` - Object validation
|
|
742
|
+
- `options.allowExcessProperties?: boolean` - Allow properties not defined in schema (default: true)
|
|
688
743
|
- `t.keyValueRecord(keyType, valueType)` - Corresponding to the `Record<K, V>` type
|
|
689
744
|
- `t.partial(recordType)` - Make all fields optional
|
|
690
745
|
- `t.optional(type)` - Optional field wrapper
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial.d.mts","sourceRoot":"","sources":["../../src/record/partial.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrD;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,EACnC,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAEtE,YAAY,CAAC,EACb,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CACH,KACA,WAAW,CAAC,CAAC,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"partial.d.mts","sourceRoot":"","sources":["../../src/record/partial.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrD;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,EACnC,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAEtE,YAAY,CAAC,EACb,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CACH,KACA,WAAW,CAAC,CAAC,EAAE,gBAAgB,CA0EjC,CAAC;AAEF,KAAK,gBAAgB,CACnB,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,EAC7B,gBAAgB,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,IAE5E,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,SAAS,IAAI,GAC5C,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAClB,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAElE,KAAK,WAAW,CACd,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,EAC7B,gBAAgB,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,IAC1E,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC"}
|
package/dist/record/partial.mjs
CHANGED
|
@@ -33,8 +33,9 @@ const partial = (recordType, options) => {
|
|
|
33
33
|
// overwrite with `a`
|
|
34
34
|
...a,
|
|
35
35
|
};
|
|
36
|
+
const validationResult = recordType.validate(objectFilled);
|
|
36
37
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
37
|
-
return
|
|
38
|
+
return Result.map(validationResult, Obj.pick(Object.keys(a)));
|
|
38
39
|
};
|
|
39
40
|
const fill = (a) => {
|
|
40
41
|
if (!isRecord(a)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial.mjs","sources":["../../src/record/partial.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAKA;;;AAGG;MACU,OAAO,GAAG,CAIrB,UAAa,EACb,OAKC,KACmC;AAGpC,IAAA,MAAM,cAAc,GAClB,OAAO,EAAE,QAAQ;AACjB,SAAC,OAAO,EAAE,gBAAgB,KAAK;AAC7B,cAAE,CAAA,QAAA,EAAW,UAAU,CAAC,QAAQ,CAAA,CAAA;AAChC,cAAE,CAAA,iBAAA,EAAoB,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,CAAA,CAAG,CAAC;AAExF,IAAA,MAAM,gBAAgB,GACpB,OAAO,EAAE,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;;AAGnE,IAAA,MAAM,YAAY,GAAM,GAAG,CAAC,IAAI,CAC9B,UAAU,CAAC,YAAY,EACvB,gBAAgB,CACZ;AAEN,IAAA,MAAM,QAAQ,GAAwB,CAAC,CAAC,KAAI;AAC1C,QAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;YAChB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA,8BAA8B,CAAC;AAC7B,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,QAAQ;AACtB,oBAAA,QAAQ,EAAE,cAAc;iBACzB,CAAC;AACH,aAAA,CAAC;;;AAIJ,QAAA,MAAM,YAAY,GAAG;;YAEnB,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,gBAAgB,CAAC;;AAEtD,YAAA,GAAG,CAAC;SACQ
|
|
1
|
+
{"version":3,"file":"partial.mjs","sources":["../../src/record/partial.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAKA;;;AAGG;MACU,OAAO,GAAG,CAIrB,UAAa,EACb,OAKC,KACmC;AAGpC,IAAA,MAAM,cAAc,GAClB,OAAO,EAAE,QAAQ;AACjB,SAAC,OAAO,EAAE,gBAAgB,KAAK;AAC7B,cAAE,CAAA,QAAA,EAAW,UAAU,CAAC,QAAQ,CAAA,CAAA;AAChC,cAAE,CAAA,iBAAA,EAAoB,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,CAAA,CAAG,CAAC;AAExF,IAAA,MAAM,gBAAgB,GACpB,OAAO,EAAE,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;;AAGnE,IAAA,MAAM,YAAY,GAAM,GAAG,CAAC,IAAI,CAC9B,UAAU,CAAC,YAAY,EACvB,gBAAgB,CACZ;AAEN,IAAA,MAAM,QAAQ,GAAwB,CAAC,CAAC,KAAI;AAC1C,QAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;YAChB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA,8BAA8B,CAAC;AAC7B,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,QAAQ;AACtB,oBAAA,QAAQ,EAAE,cAAc;iBACzB,CAAC;AACH,aAAA,CAAC;;;AAIJ,QAAA,MAAM,YAAY,GAAG;;YAEnB,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,gBAAgB,CAAC;;AAEtD,YAAA,GAAG,CAAC;SACQ;QAEd,MAAM,gBAAgB,GAAG,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC;;AAG1D,QAAA,OAAO,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAE3D;AACH,IAAA,CAAC;AAED,IAAA,MAAM,IAAI,GAAoB,CAAC,CAAC,KAAI;AAClC,QAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;AAChB,YAAA,OAAO,YAAY;;AAGrB,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;QAG7C,OAAO,GAAG,CAAC,IAAI;;AAEb,QAAA,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;;AAElB,QAAA,gBAAgB,CAAC,MAAM,CACrB,CAAC,CAAC;;QAEA,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CACpB,CACc;AACnB,IAAA,CAAC;IAED,OAAO;AACL,QAAA,QAAQ,EAAE,cAAc;QACxB,YAAY;QACZ,IAAI;QACJ,QAAQ;AACR,QAAA,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;AACxB,QAAA,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC;AAClC,QAAA,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;KAC7B;AACH;AAeA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;"}
|
package/dist/record/record.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Type, type TypeOf } from '../type.mjs';
|
|
2
2
|
export declare const record: <const R extends Record<string, Type<unknown>>>(source: R, options?: Partial<Readonly<{
|
|
3
3
|
typeName: string;
|
|
4
|
+
/** @default true */
|
|
5
|
+
allowExcessProperties: boolean;
|
|
4
6
|
}>>) => Type<RecordTypeValue<R>>;
|
|
5
7
|
type RecordTypeValue<R extends Record<string, Type<unknown>>> = TsFortressInternal.RecordTypeValueImpl<R>;
|
|
6
8
|
declare namespace TsFortressInternal {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.d.mts","sourceRoot":"","sources":["../../src/record/record.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AASrD,eAAO,MAAM,MAAM,GAAI,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,EAClE,QAAQ,CAAC,EACT,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"record.d.mts","sourceRoot":"","sources":["../../src/record/record.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AASrD,eAAO,MAAM,MAAM,GAAI,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,EAClE,QAAQ,CAAC,EACT,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IAEjB,oBAAoB;IACpB,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC,CACH,KACA,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAwGzB,CAAC;AAEF,KAAK,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,IAC1D,kBAAkB,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE5C,kBAAU,kBAAkB,CAAC;IAC3B,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,IACrE,sBAAsB,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjD,KAAK,sBAAsB,CACzB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,EACvC,YAAY,SAAS,MAAM,CAAC,IAC1B,QAAQ,CACV;SACG,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KACvC,GAAG;SACD,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KACxD,CACF,CAAC;IAEF,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI;SAC9D,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;YAAE,QAAQ,EAAE,IAAI,CAAA;SAAE,GAAG,CAAC,GAAG,KAAK;KAC5D,CAAC,MAAM,CAAC,CAAC,CAAC;;CACZ"}
|
package/dist/record/record.mjs
CHANGED
|
@@ -5,10 +5,12 @@ import { createIsFn } from '../utils/create-is-fn.mjs';
|
|
|
5
5
|
import { createPrimitiveValidationError, prependPathToValidationErrors } from '../validation-error.mjs';
|
|
6
6
|
|
|
7
7
|
const record = (source, options) => {
|
|
8
|
+
const sourceKeys = new Set(Object.keys(source));
|
|
8
9
|
const typeNameFilled = options?.typeName ??
|
|
9
10
|
`{ ${Object.entries(source)
|
|
10
11
|
.map(([k, v]) => `${k}: ${v.typeName}`)
|
|
11
12
|
.join(', ')} }`;
|
|
13
|
+
const allowExcessProperties = options?.allowExcessProperties ?? true;
|
|
12
14
|
const defaultValue =
|
|
13
15
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
14
16
|
Object.fromEntries(Object.entries(source).map(([key, value]) => tp(key, value.defaultValue)));
|
|
@@ -22,7 +24,7 @@ const record = (source, options) => {
|
|
|
22
24
|
}),
|
|
23
25
|
]);
|
|
24
26
|
}
|
|
25
|
-
const
|
|
27
|
+
const defaultErrors = Object.entries(source).flatMap(([k, valueType]) => {
|
|
26
28
|
if (!Object.hasOwn(a, k)) {
|
|
27
29
|
if (source[k]?.optional === true)
|
|
28
30
|
return [];
|
|
@@ -43,8 +45,22 @@ const record = (source, options) => {
|
|
|
43
45
|
}
|
|
44
46
|
return [];
|
|
45
47
|
});
|
|
46
|
-
if
|
|
47
|
-
|
|
48
|
+
// Check for excess properties if allowExcessProperties is false
|
|
49
|
+
if (!allowExcessProperties) {
|
|
50
|
+
const excessKeys = Object.keys(a).filter((key) => !sourceKeys.has(key));
|
|
51
|
+
if (excessKeys.length > 0) {
|
|
52
|
+
const excessErrors = excessKeys.map((key) => ({
|
|
53
|
+
path: [key],
|
|
54
|
+
actualValue: a[key],
|
|
55
|
+
typeName: typeNameFilled,
|
|
56
|
+
expectedType: typeNameFilled,
|
|
57
|
+
message: `Excess property "${key}" is not allowed`,
|
|
58
|
+
}));
|
|
59
|
+
return Result.err([...defaultErrors, ...excessErrors]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (defaultErrors.length > 0) {
|
|
63
|
+
return Result.err(defaultErrors);
|
|
48
64
|
}
|
|
49
65
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
50
66
|
return Result.ok(a);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.mjs","sources":["../../src/record/record.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;MAUa,MAAM,GAAG,CACpB,MAAS,EACT,
|
|
1
|
+
{"version":3,"file":"record.mjs","sources":["../../src/record/record.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
2
|
import { number } from '../primitives/index.mjs';
|
|
3
3
|
import { type TypeOf } from '../type.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type ValidationError,
|
|
6
|
+
validationErrorsToMessages,
|
|
7
|
+
} from '../validation-error.mjs';
|
|
5
8
|
import { arrayOfLength } from './array-of-length.mjs';
|
|
6
9
|
|
|
7
10
|
describe('arrayOfLength', () => {
|
|
@@ -74,6 +77,18 @@ describe('arrayOfLength', () => {
|
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
describe('validate', () => {
|
|
80
|
+
test('truthy case', () => {
|
|
81
|
+
const ys: unknown = [5, 6, 7, 8];
|
|
82
|
+
|
|
83
|
+
const result = xs.validate(ys);
|
|
84
|
+
expectType<typeof result, Result<Xs, readonly ValidationError[]>>('=');
|
|
85
|
+
expect(Result.isOk(result)).toBe(true);
|
|
86
|
+
|
|
87
|
+
if (Result.isOk(result)) {
|
|
88
|
+
expect(result.value).toStrictEqual([5, 6, 7, 8]);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
77
92
|
test('falsy case 1', () => {
|
|
78
93
|
const ys: unknown = [];
|
|
79
94
|
|
package/src/array/array.test.mts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
2
|
import { number } from '../primitives/index.mjs';
|
|
3
3
|
import { type TypeOf } from '../type.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type ValidationError,
|
|
6
|
+
validationErrorsToMessages,
|
|
7
|
+
} from '../validation-error.mjs';
|
|
5
8
|
import { array } from './array.mjs';
|
|
6
9
|
|
|
7
10
|
describe('array', () => {
|
|
@@ -58,6 +61,18 @@ describe('array', () => {
|
|
|
58
61
|
});
|
|
59
62
|
|
|
60
63
|
describe('validate', () => {
|
|
64
|
+
test('truthy case', () => {
|
|
65
|
+
const ys: unknown = [1, 2, 3];
|
|
66
|
+
|
|
67
|
+
const result = xs.validate(ys);
|
|
68
|
+
expectType<typeof result, Result<Xs, readonly ValidationError[]>>('=');
|
|
69
|
+
expect(Result.isOk(result)).toBe(true);
|
|
70
|
+
|
|
71
|
+
if (Result.isOk(result)) {
|
|
72
|
+
expect(result.value).toStrictEqual([1, 2, 3]);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
61
76
|
test('falsy case', () => {
|
|
62
77
|
const ys: unknown = ['1', '', 3];
|
|
63
78
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
2
|
import { number } from '../primitives/index.mjs';
|
|
3
3
|
import { type TypeOf } from '../type.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type ValidationError,
|
|
6
|
+
validationErrorsToMessages,
|
|
7
|
+
} from '../validation-error.mjs';
|
|
5
8
|
import { nonEmptyArray } from './non-empty-array.mjs';
|
|
6
9
|
|
|
7
10
|
describe('nonEmptyArray', () => {
|
|
@@ -74,6 +77,18 @@ describe('nonEmptyArray', () => {
|
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
describe('validate', () => {
|
|
80
|
+
test('truthy case', () => {
|
|
81
|
+
const ys: unknown = [1, 2, 3];
|
|
82
|
+
|
|
83
|
+
const result = xs.validate(ys);
|
|
84
|
+
expectType<typeof result, Result<Xs, readonly ValidationError[]>>('=');
|
|
85
|
+
expect(Result.isOk(result)).toBe(true);
|
|
86
|
+
|
|
87
|
+
if (Result.isOk(result)) {
|
|
88
|
+
expect(result.value).toStrictEqual([1, 2, 3]);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
77
92
|
test('falsy case 1', () => {
|
|
78
93
|
const ys: unknown = [];
|
|
79
94
|
|
package/src/array/tuple.test.mts
CHANGED
|
@@ -2,7 +2,10 @@ import { expectType, Result } from 'ts-data-forge';
|
|
|
2
2
|
import { number, numberLiteral, stringLiteral } from '../primitives/index.mjs';
|
|
3
3
|
import { record } from '../record/index.mjs';
|
|
4
4
|
import { type TypeOf } from '../type.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type ValidationError,
|
|
7
|
+
validationErrorsToMessages,
|
|
8
|
+
} from '../validation-error.mjs';
|
|
6
9
|
import { tuple } from './tuple.mjs';
|
|
7
10
|
|
|
8
11
|
describe('tuple', () => {
|
|
@@ -72,6 +75,20 @@ describe('tuple', () => {
|
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
describe('validate', () => {
|
|
78
|
+
test('truthy case', () => {
|
|
79
|
+
const x: unknown = [{ x: 1, y: 2 }, 3, '2'];
|
|
80
|
+
|
|
81
|
+
const result = targetType.validate(x);
|
|
82
|
+
expectType<typeof result, Result<TargetType, readonly ValidationError[]>>(
|
|
83
|
+
'=',
|
|
84
|
+
);
|
|
85
|
+
expect(Result.isOk(result)).toBe(true);
|
|
86
|
+
|
|
87
|
+
if (Result.isOk(result)) {
|
|
88
|
+
expect(result.value).toStrictEqual([{ x: 1, y: 2 }, 3, '2']);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
75
92
|
test('falsy case - not array', () => {
|
|
76
93
|
const x: unknown = 'not an array';
|
|
77
94
|
|
|
@@ -3,7 +3,10 @@ import { uintRange } from '../enum/index.mjs';
|
|
|
3
3
|
import { number } from '../primitives/index.mjs';
|
|
4
4
|
import { record } from '../record/index.mjs';
|
|
5
5
|
import { type TypeOf } from '../type.mjs';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type ValidationError,
|
|
8
|
+
validationErrorsToMessages,
|
|
9
|
+
} from '../validation-error.mjs';
|
|
7
10
|
import { intersection } from './intersection.mjs';
|
|
8
11
|
|
|
9
12
|
describe('intersection', () => {
|
|
@@ -74,6 +77,19 @@ describe('intersection', () => {
|
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
describe('validate', () => {
|
|
80
|
+
test('truthy case', () => {
|
|
81
|
+
const result = targetType.validate({ x: 0, y: 1, z: 2, w: 3 });
|
|
82
|
+
expectType<
|
|
83
|
+
typeof result,
|
|
84
|
+
Result<TargetType, readonly ValidationError[]>
|
|
85
|
+
>('=');
|
|
86
|
+
expect(Result.isOk(result)).toBe(true);
|
|
87
|
+
|
|
88
|
+
if (Result.isOk(result)) {
|
|
89
|
+
expect(result.value).toStrictEqual({ x: 0, y: 1, z: 2, w: 3 });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
77
93
|
test('falsy case', () => {
|
|
78
94
|
const result = targetType.validate({ x: 0, y: 1 });
|
|
79
95
|
expect(Result.isErr(result)).toBe(true);
|
|
@@ -165,6 +181,19 @@ describe('intersection', () => {
|
|
|
165
181
|
});
|
|
166
182
|
|
|
167
183
|
describe('validate', () => {
|
|
184
|
+
test('truthy case', () => {
|
|
185
|
+
const result = targetType.validate(0);
|
|
186
|
+
expectType<
|
|
187
|
+
typeof result,
|
|
188
|
+
Result<TargetType, readonly ValidationError[]>
|
|
189
|
+
>('=');
|
|
190
|
+
expect(Result.isOk(result)).toBe(true);
|
|
191
|
+
|
|
192
|
+
if (Result.isOk(result)) {
|
|
193
|
+
expect(result.value).toBe(0);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
168
197
|
test('falsy case', () => {
|
|
169
198
|
const result = targetType.validate('aaa');
|
|
170
199
|
expect(Result.isErr(result)).toBe(true);
|
|
@@ -278,6 +307,19 @@ describe('intersection', () => {
|
|
|
278
307
|
});
|
|
279
308
|
|
|
280
309
|
describe('validate', () => {
|
|
310
|
+
test('truthy case', () => {
|
|
311
|
+
const result = targetType.validate(3);
|
|
312
|
+
expectType<
|
|
313
|
+
typeof result,
|
|
314
|
+
Result<TargetType, readonly ValidationError[]>
|
|
315
|
+
>('=');
|
|
316
|
+
expect(Result.isOk(result)).toBe(true);
|
|
317
|
+
|
|
318
|
+
if (Result.isOk(result)) {
|
|
319
|
+
expect(result.value).toBe(3);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
281
323
|
test('falsy case', () => {
|
|
282
324
|
const result = targetType.validate(7);
|
|
283
325
|
expect(Result.isErr(result)).toBe(true);
|
|
@@ -2,7 +2,10 @@ import { expectType, Result } from 'ts-data-forge';
|
|
|
2
2
|
import { number } from '../primitives/index.mjs';
|
|
3
3
|
import { record } from '../record/index.mjs';
|
|
4
4
|
import { type TypeOf } from '../type.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type ValidationError,
|
|
7
|
+
validationErrorsToMessages,
|
|
8
|
+
} from '../validation-error.mjs';
|
|
6
9
|
import { mergeRecords } from './merge-records.mjs';
|
|
7
10
|
|
|
8
11
|
describe('mergeRecords', () => {
|
|
@@ -67,6 +70,18 @@ describe('mergeRecords', () => {
|
|
|
67
70
|
});
|
|
68
71
|
|
|
69
72
|
describe('validate', () => {
|
|
73
|
+
test('truthy case', () => {
|
|
74
|
+
const result = targetType.validate({ x: 0, y: 1, z: 2, w: 3 });
|
|
75
|
+
expectType<typeof result, Result<TargetType, readonly ValidationError[]>>(
|
|
76
|
+
'=',
|
|
77
|
+
);
|
|
78
|
+
expect(Result.isOk(result)).toBe(true);
|
|
79
|
+
|
|
80
|
+
if (Result.isOk(result)) {
|
|
81
|
+
expect(result.value).toStrictEqual({ x: 0, y: 1, z: 2, w: 3 });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
70
85
|
test('falsy case', () => {
|
|
71
86
|
const result = targetType.validate({ x: 0, y: 1 });
|
|
72
87
|
expect(Result.isErr(result)).toBe(true);
|
|
@@ -2,7 +2,10 @@ import { expectType, Result } from 'ts-data-forge';
|
|
|
2
2
|
import { number, numberLiteral, stringLiteral } from '../primitives/index.mjs';
|
|
3
3
|
import { record } from '../record/index.mjs';
|
|
4
4
|
import { type TypeOf } from '../type.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type ValidationError,
|
|
7
|
+
validationErrorsToMessages,
|
|
8
|
+
} from '../validation-error.mjs';
|
|
6
9
|
import { union } from './union.mjs';
|
|
7
10
|
|
|
8
11
|
describe('union', () => {
|
|
@@ -70,6 +73,18 @@ describe('union', () => {
|
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
describe('validate', () => {
|
|
76
|
+
test('truthy case', () => {
|
|
77
|
+
const result = targetType.validate(3);
|
|
78
|
+
expectType<typeof result, Result<TargetType, readonly ValidationError[]>>(
|
|
79
|
+
'=',
|
|
80
|
+
);
|
|
81
|
+
expect(Result.isOk(result)).toBe(true);
|
|
82
|
+
|
|
83
|
+
if (Result.isOk(result)) {
|
|
84
|
+
expect(result.value).toBe(3);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
73
88
|
test('falsy case', () => {
|
|
74
89
|
const result = targetType.validate(5);
|
|
75
90
|
expect(Result.isErr(result)).toBe(true);
|
package/src/enum/enum.test.mts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
2
|
import { type TypeOf } from '../type.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type ValidationError,
|
|
5
|
+
validationErrorsToMessages,
|
|
6
|
+
} from '../validation-error.mjs';
|
|
4
7
|
import { enumType } from './enum.mjs';
|
|
5
8
|
|
|
6
9
|
describe('enumType', () => {
|
|
@@ -41,6 +44,18 @@ describe('enumType', () => {
|
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
describe('validate', () => {
|
|
47
|
+
test('truthy case', () => {
|
|
48
|
+
const result = targetType.validate(3);
|
|
49
|
+
expectType<typeof result, Result<TargetType, readonly ValidationError[]>>(
|
|
50
|
+
'=',
|
|
51
|
+
);
|
|
52
|
+
expect(Result.isOk(result)).toBe(true);
|
|
53
|
+
|
|
54
|
+
if (Result.isOk(result)) {
|
|
55
|
+
expect(result.value).toBe(3);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
44
59
|
test('falsy case', () => {
|
|
45
60
|
const result = targetType.validate(5);
|
|
46
61
|
expect(Result.isErr(result)).toBe(true);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
2
|
import { type TypeOf } from '../type.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type ValidationError,
|
|
5
|
+
validationErrorsToMessages,
|
|
6
|
+
} from '../validation-error.mjs';
|
|
4
7
|
import { uintRange } from './uint-range.mjs';
|
|
5
8
|
|
|
6
9
|
describe('uintRange', () => {
|
|
@@ -44,6 +47,16 @@ describe('uintRange', () => {
|
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
describe('validate', () => {
|
|
50
|
+
test('truthy case', () => {
|
|
51
|
+
const result = month.validate(5);
|
|
52
|
+
expectType<typeof result, Result<Month, readonly ValidationError[]>>('=');
|
|
53
|
+
expect(Result.isOk(result)).toBe(true);
|
|
54
|
+
|
|
55
|
+
if (Result.isOk(result)) {
|
|
56
|
+
expect(result.value).toBe(5);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
47
60
|
test('falsy case', () => {
|
|
48
61
|
const result = month.validate(13);
|
|
49
62
|
expect(Result.isErr(result)).toBe(true);
|