ts-fortress 12.0.3 → 12.0.4
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/dist/primitives/bigint.mjs +13 -10
- package/dist/primitives/bigint.mjs.map +1 -1
- package/dist/primitives/number.mjs +13 -10
- package/dist/primitives/number.mjs.map +1 -1
- package/dist/record/partial.d.mts.map +1 -1
- package/dist/record/partial.mjs +4 -5
- package/dist/record/partial.mjs.map +1 -1
- package/dist/record/record.d.mts.map +1 -1
- package/dist/record/record.mjs.map +1 -1
- package/dist/record/required.d.mts.map +1 -1
- package/dist/record/required.mjs +4 -5
- package/dist/record/required.mjs.map +1 -1
- package/package.json +10 -10
- package/src/primitives/bigint.mts +13 -10
- package/src/primitives/number.mts +13 -10
- package/src/record/partial.mts +3 -5
- package/src/record/record.mts +5 -1
- package/src/record/required.mts +3 -5
|
@@ -71,35 +71,35 @@ const createConstraintsPredicate = (constraints) => (value) => {
|
|
|
71
71
|
return Result.err({ constraint: "nonPositive", value: true });
|
|
72
72
|
}
|
|
73
73
|
if (gt !== void 0 && !(value > gt)) {
|
|
74
|
-
return Result.err({ constraint: "gt", value:
|
|
74
|
+
return Result.err({ constraint: "gt", value: gt.toString() });
|
|
75
75
|
}
|
|
76
76
|
if (gte !== void 0 && !(value >= gte)) {
|
|
77
|
-
return Result.err({ constraint: "gte", value:
|
|
77
|
+
return Result.err({ constraint: "gte", value: gte.toString() });
|
|
78
78
|
}
|
|
79
79
|
if (min !== void 0 && !(value >= min)) {
|
|
80
|
-
return Result.err({ constraint: "min", value:
|
|
80
|
+
return Result.err({ constraint: "min", value: min.toString() });
|
|
81
81
|
}
|
|
82
82
|
if (lt !== void 0 && !(value < lt)) {
|
|
83
|
-
return Result.err({ constraint: "lt", value:
|
|
83
|
+
return Result.err({ constraint: "lt", value: lt.toString() });
|
|
84
84
|
}
|
|
85
85
|
if (lte !== void 0 && !(value <= lte)) {
|
|
86
|
-
return Result.err({ constraint: "lte", value:
|
|
86
|
+
return Result.err({ constraint: "lte", value: lte.toString() });
|
|
87
87
|
}
|
|
88
88
|
if (max !== void 0 && !(value <= max)) {
|
|
89
|
-
return Result.err({ constraint: "max", value:
|
|
89
|
+
return Result.err({ constraint: "max", value: max.toString() });
|
|
90
90
|
}
|
|
91
91
|
if (multipleOf !== void 0) {
|
|
92
92
|
if (multipleOf === 0n) {
|
|
93
93
|
if (value !== 0n) {
|
|
94
94
|
return Result.err({
|
|
95
95
|
constraint: "multipleOf",
|
|
96
|
-
value:
|
|
96
|
+
value: multipleOf.toString()
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
} else if (value % multipleOf !== 0n) {
|
|
100
100
|
return Result.err({
|
|
101
101
|
constraint: "multipleOf",
|
|
102
|
-
value:
|
|
102
|
+
value: multipleOf.toString()
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -108,11 +108,14 @@ const createConstraintsPredicate = (constraints) => (value) => {
|
|
|
108
108
|
if (value !== 0n) {
|
|
109
109
|
return Result.err({
|
|
110
110
|
constraint: "step",
|
|
111
|
-
value:
|
|
111
|
+
value: step.toString()
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
} else if (value % step !== 0n) {
|
|
115
|
-
return Result.err({
|
|
115
|
+
return Result.err({
|
|
116
|
+
constraint: "step",
|
|
117
|
+
value: step.toString()
|
|
118
|
+
});
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
return Result.ok(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bigint.mjs","sources":["../../src/primitives/bigint.mts"],"sourcesContent":["/* eslint-disable unicorn/no-negated-comparison */\nimport { Arr, expectType, isBigint, Result } from 'ts-data-forge';\nimport { type BoolAnd, type BoolNot } from 'ts-type-forge';\nimport { refine } from '../other-types/index.mjs';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveType,\n type NumericConstraintViolation,\n} from '../utils/index.mjs';\n\ntype NumberType = bigint;\n\nexport function bigint(defaultValue?: NumberType): Type<NumberType>;\n\nexport function bigint<N extends NumberType, const C extends Constraints>(\n defaultValue: N & DefaultValueType<N, C>,\n constraints: C,\n): Type<NumberType>;\n\nexport function bigint<C extends Constraints>(\n defaultValue: NumberType = 0n,\n constraints?: C,\n): Type<NumberType> {\n const baseType = createPrimitiveType({\n typeName: 'bigint',\n defaultValue,\n is: isBigint,\n });\n\n if (constraints === undefined || Arr.isEmpty(Object.keys(constraints))) {\n return baseType;\n }\n\n const constraintsPredicate = createConstraintsPredicate(constraints);\n\n const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);\n\n if (Result.isErr(defaultValueConstraintsCheck)) {\n throw new Error(\n defaultValueErrorMessage(\n defaultValue,\n defaultValueConstraintsCheck.value,\n ),\n );\n }\n\n return refine({\n baseType,\n defaultValue,\n is: (value): value is NumberType =>\n Result.isOk(constraintsPredicate(value)),\n typeName: 'bigint',\n getConstraintDetails: (value) => {\n const result = constraintsPredicate(value);\n\n return Result.isErr(result)\n ? {\n kind: 'numeric-constraint',\n numericType: 'bigint',\n violation: result.value,\n }\n : undefined;\n },\n });\n}\n\ntype Constraints = Partial<\n Readonly<{\n nonZero: true;\n negative: true;\n nonNegative: true;\n positive: true;\n nonPositive: true;\n\n gt: NumberType;\n gte: NumberType;\n min: NumberType;\n lt: NumberType;\n lte: NumberType;\n max: NumberType;\n multipleOf: NumberType;\n step: NumberType;\n }>\n>;\n\ntype DefaultValueType<\n N extends NumberType,\n C extends Constraints,\n> = DefaultValueWhenNonZeroIsOn<N, C> &\n DefaultValueWhenNegativeIsOn<N, C> &\n DefaultValueWhenNonNegativeIsOn<N, C> &\n DefaultValueWhenPositiveIsOn<N, C> &\n DefaultValueWhenNonPositiveIsOn<N, C>;\n\ntype DefaultValueWhenNonZeroIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ nonZero: true }> ? NonZeroNumber<N> : NumberType;\n\ntype DefaultValueWhenNegativeIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ negative: true }> ? NegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenNonNegativeIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonNegative: true }> ? NonNegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenPositiveIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ positive: true }> ? PositiveNumber<N> : NumberType;\n\ntype DefaultValueWhenNonPositiveIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonPositive: true }> ? NonPositiveNumber<N> : NumberType;\n\ntype NonZeroNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsZero<N> extends true\n ? never\n : N;\n\ntype NegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNegative<N> extends true\n ? N\n : never;\n\ntype NonNegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonNegative<N> extends true\n ? N\n : never;\n\ntype PositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsPositive<N> extends true\n ? N\n : never;\n\ntype NonPositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonPositive<N> extends true\n ? N\n : never;\n\ntype IsZero<N extends NumberType> = `${N}` extends '0' ? true : false;\n\ntype IsNonZero<N extends NumberType> = IsZero<N> extends true ? false : true;\n\ntype IsNegative<N extends NumberType> = `${N}` extends `-${string}`\n ? true\n : false;\n\ntype IsNonNegative<N extends NumberType> =\n IsNegative<N> extends true ? false : true;\n\ntype IsPositive<N extends NumberType> = BoolAnd<IsNonZero<N>, IsNonNegative<N>>;\n\ntype IsNonPositive<N extends NumberType> = BoolNot<IsPositive<N>>;\n\nconst createConstraintsPredicate =\n (constraints: Constraints) =>\n (value: NumberType): Result<true, NumericConstraintViolation> => {\n const {\n nonZero,\n negative,\n nonNegative,\n positive,\n nonPositive,\n gt,\n gte,\n min,\n lt,\n lte,\n max,\n multipleOf,\n step,\n ..._rest\n } = constraints;\n\n expectType<keyof typeof _rest, never>('=');\n\n if (nonZero === true && !(value !== 0n)) {\n return Result.err({ constraint: 'nonZero', value: true } as const);\n }\n\n if (negative === true && !(value < 0n)) {\n return Result.err({ constraint: 'negative', value: true } as const);\n }\n\n if (nonNegative === true && !(value >= 0n)) {\n return Result.err({ constraint: 'nonNegative', value: true } as const);\n }\n\n if (positive === true && !(value > 0n)) {\n return Result.err({ constraint: 'positive', value: true } as const);\n }\n\n if (nonPositive === true && !(value <= 0n)) {\n return Result.err({ constraint: 'nonPositive', value: true } as const);\n }\n\n if (gt !== undefined && !(value > gt)) {\n return Result.err({ constraint: 'gt', value: String(gt) } as const);\n }\n\n if (gte !== undefined && !(value >= gte)) {\n return Result.err({ constraint: 'gte', value: String(gte) } as const);\n }\n\n if (min !== undefined && !(value >= min)) {\n return Result.err({ constraint: 'min', value: String(min) } as const);\n }\n\n if (lt !== undefined && !(value < lt)) {\n return Result.err({ constraint: 'lt', value: String(lt) } as const);\n }\n\n if (lte !== undefined && !(value <= lte)) {\n return Result.err({ constraint: 'lte', value: String(lte) } as const);\n }\n\n if (max !== undefined && !(value <= max)) {\n return Result.err({ constraint: 'max', value: String(max) } as const);\n }\n\n // `value % 0n` throws a RangeError, so the zero divisor is handled\n // separately: it only admits zero.\n if (multipleOf !== undefined) {\n if (multipleOf === 0n) {\n if (value !== 0n) {\n return Result.err({\n constraint: 'multipleOf',\n value: String(multipleOf),\n } as const);\n }\n } else if (value % multipleOf !== 0n) {\n return Result.err({\n constraint: 'multipleOf',\n value: String(multipleOf),\n } as const);\n }\n }\n\n if (step !== undefined) {\n if (step === 0n) {\n if (value !== 0n) {\n return Result.err({\n constraint: 'step',\n value: String(step),\n } as const);\n }\n } else if (value % step !== 0n) {\n return Result.err({ constraint: 'step', value: String(step) } as const);\n }\n }\n\n return Result.ok(true);\n };\n\nconst defaultValueErrorMessage = (\n value: NumberType,\n violation: NumericConstraintViolation,\n): string =>\n `defaultValue [${value}] for bigint does not satisfy the constraint ${violation.constraint} = ${violation.value}` as const;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bigint.mjs","sources":["../../src/primitives/bigint.mts"],"sourcesContent":["/* eslint-disable unicorn/no-negated-comparison */\nimport { Arr, expectType, isBigint, Result } from 'ts-data-forge';\nimport { type BoolAnd, type BoolNot } from 'ts-type-forge';\nimport { refine } from '../other-types/index.mjs';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveType,\n type NumericConstraintViolation,\n} from '../utils/index.mjs';\n\ntype NumberType = bigint;\n\nexport function bigint(defaultValue?: NumberType): Type<NumberType>;\n\nexport function bigint<N extends NumberType, const C extends Constraints>(\n defaultValue: N & DefaultValueType<N, C>,\n constraints: C,\n): Type<NumberType>;\n\nexport function bigint<C extends Constraints>(\n defaultValue: NumberType = 0n,\n constraints?: C,\n): Type<NumberType> {\n const baseType = createPrimitiveType({\n typeName: 'bigint',\n defaultValue,\n is: isBigint,\n });\n\n if (constraints === undefined || Arr.isEmpty(Object.keys(constraints))) {\n return baseType;\n }\n\n const constraintsPredicate = createConstraintsPredicate(constraints);\n\n const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);\n\n if (Result.isErr(defaultValueConstraintsCheck)) {\n throw new Error(\n defaultValueErrorMessage(\n defaultValue,\n defaultValueConstraintsCheck.value,\n ),\n );\n }\n\n return refine({\n baseType,\n defaultValue,\n is: (value): value is NumberType =>\n Result.isOk(constraintsPredicate(value)),\n typeName: 'bigint',\n getConstraintDetails: (value) => {\n const result = constraintsPredicate(value);\n\n return Result.isErr(result)\n ? {\n kind: 'numeric-constraint',\n numericType: 'bigint',\n violation: result.value,\n }\n : undefined;\n },\n });\n}\n\ntype Constraints = Partial<\n Readonly<{\n nonZero: true;\n negative: true;\n nonNegative: true;\n positive: true;\n nonPositive: true;\n\n gt: NumberType;\n gte: NumberType;\n min: NumberType;\n lt: NumberType;\n lte: NumberType;\n max: NumberType;\n multipleOf: NumberType;\n step: NumberType;\n }>\n>;\n\ntype DefaultValueType<\n N extends NumberType,\n C extends Constraints,\n> = DefaultValueWhenNonZeroIsOn<N, C> &\n DefaultValueWhenNegativeIsOn<N, C> &\n DefaultValueWhenNonNegativeIsOn<N, C> &\n DefaultValueWhenPositiveIsOn<N, C> &\n DefaultValueWhenNonPositiveIsOn<N, C>;\n\ntype DefaultValueWhenNonZeroIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ nonZero: true }> ? NonZeroNumber<N> : NumberType;\n\ntype DefaultValueWhenNegativeIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ negative: true }> ? NegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenNonNegativeIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonNegative: true }> ? NonNegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenPositiveIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ positive: true }> ? PositiveNumber<N> : NumberType;\n\ntype DefaultValueWhenNonPositiveIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonPositive: true }> ? NonPositiveNumber<N> : NumberType;\n\ntype NonZeroNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsZero<N> extends true\n ? never\n : N;\n\ntype NegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNegative<N> extends true\n ? N\n : never;\n\ntype NonNegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonNegative<N> extends true\n ? N\n : never;\n\ntype PositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsPositive<N> extends true\n ? N\n : never;\n\ntype NonPositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonPositive<N> extends true\n ? N\n : never;\n\ntype IsZero<N extends NumberType> = `${N}` extends '0' ? true : false;\n\ntype IsNonZero<N extends NumberType> = IsZero<N> extends true ? false : true;\n\ntype IsNegative<N extends NumberType> = `${N}` extends `-${string}`\n ? true\n : false;\n\ntype IsNonNegative<N extends NumberType> =\n IsNegative<N> extends true ? false : true;\n\ntype IsPositive<N extends NumberType> = BoolAnd<IsNonZero<N>, IsNonNegative<N>>;\n\ntype IsNonPositive<N extends NumberType> = BoolNot<IsPositive<N>>;\n\nconst createConstraintsPredicate =\n (constraints: Constraints) =>\n (value: NumberType): Result<true, NumericConstraintViolation> => {\n const {\n nonZero,\n negative,\n nonNegative,\n positive,\n nonPositive,\n gt,\n gte,\n min,\n lt,\n lte,\n max,\n multipleOf,\n step,\n ..._rest\n } = constraints;\n\n expectType<keyof typeof _rest, never>('=');\n\n if (nonZero === true && !(value !== 0n)) {\n return Result.err({ constraint: 'nonZero', value: true } as const);\n }\n\n if (negative === true && !(value < 0n)) {\n return Result.err({ constraint: 'negative', value: true } as const);\n }\n\n if (nonNegative === true && !(value >= 0n)) {\n return Result.err({ constraint: 'nonNegative', value: true } as const);\n }\n\n if (positive === true && !(value > 0n)) {\n return Result.err({ constraint: 'positive', value: true } as const);\n }\n\n if (nonPositive === true && !(value <= 0n)) {\n return Result.err({ constraint: 'nonPositive', value: true } as const);\n }\n\n if (gt !== undefined && !(value > gt)) {\n return Result.err({ constraint: 'gt', value: gt.toString() } as const);\n }\n\n if (gte !== undefined && !(value >= gte)) {\n return Result.err({ constraint: 'gte', value: gte.toString() } as const);\n }\n\n if (min !== undefined && !(value >= min)) {\n return Result.err({ constraint: 'min', value: min.toString() } as const);\n }\n\n if (lt !== undefined && !(value < lt)) {\n return Result.err({ constraint: 'lt', value: lt.toString() } as const);\n }\n\n if (lte !== undefined && !(value <= lte)) {\n return Result.err({ constraint: 'lte', value: lte.toString() } as const);\n }\n\n if (max !== undefined && !(value <= max)) {\n return Result.err({ constraint: 'max', value: max.toString() } as const);\n }\n\n // `value % 0n` throws a RangeError, so the zero divisor is handled\n // separately: it only admits zero.\n if (multipleOf !== undefined) {\n if (multipleOf === 0n) {\n if (value !== 0n) {\n return Result.err({\n constraint: 'multipleOf',\n value: multipleOf.toString(),\n } as const);\n }\n } else if (value % multipleOf !== 0n) {\n return Result.err({\n constraint: 'multipleOf',\n value: multipleOf.toString(),\n } as const);\n }\n }\n\n if (step !== undefined) {\n if (step === 0n) {\n if (value !== 0n) {\n return Result.err({\n constraint: 'step',\n value: step.toString(),\n } as const);\n }\n } else if (value % step !== 0n) {\n return Result.err({\n constraint: 'step',\n value: step.toString(),\n } as const);\n }\n }\n\n return Result.ok(true);\n };\n\nconst defaultValueErrorMessage = (\n value: NumberType,\n violation: NumericConstraintViolation,\n): string =>\n `defaultValue [${value}] for bigint does not satisfy the constraint ${violation.constraint} = ${violation.value}` as const;\n"],"names":[],"mappings":"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"}
|
|
@@ -83,35 +83,35 @@ const createConstraintsPredicate = (constraints) => (value) => {
|
|
|
83
83
|
return Result.err({ constraint: "nonPositive", value: true });
|
|
84
84
|
}
|
|
85
85
|
if (gt !== void 0 && !(value > gt)) {
|
|
86
|
-
return Result.err({ constraint: "gt", value:
|
|
86
|
+
return Result.err({ constraint: "gt", value: gt.toString() });
|
|
87
87
|
}
|
|
88
88
|
if (gte !== void 0 && !(value >= gte)) {
|
|
89
|
-
return Result.err({ constraint: "gte", value:
|
|
89
|
+
return Result.err({ constraint: "gte", value: gte.toString() });
|
|
90
90
|
}
|
|
91
91
|
if (min !== void 0 && !(value >= min)) {
|
|
92
|
-
return Result.err({ constraint: "min", value:
|
|
92
|
+
return Result.err({ constraint: "min", value: min.toString() });
|
|
93
93
|
}
|
|
94
94
|
if (lt !== void 0 && !(value < lt)) {
|
|
95
|
-
return Result.err({ constraint: "lt", value:
|
|
95
|
+
return Result.err({ constraint: "lt", value: lt.toString() });
|
|
96
96
|
}
|
|
97
97
|
if (lte !== void 0 && !(value <= lte)) {
|
|
98
|
-
return Result.err({ constraint: "lte", value:
|
|
98
|
+
return Result.err({ constraint: "lte", value: lte.toString() });
|
|
99
99
|
}
|
|
100
100
|
if (max !== void 0 && !(value <= max)) {
|
|
101
|
-
return Result.err({ constraint: "max", value:
|
|
101
|
+
return Result.err({ constraint: "max", value: max.toString() });
|
|
102
102
|
}
|
|
103
103
|
if (multipleOf !== void 0) {
|
|
104
104
|
if (multipleOf === 0) {
|
|
105
105
|
if (value !== 0) {
|
|
106
106
|
return Result.err({
|
|
107
107
|
constraint: "multipleOf",
|
|
108
|
-
value:
|
|
108
|
+
value: multipleOf.toString()
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
} else if (value % multipleOf !== 0) {
|
|
112
112
|
return Result.err({
|
|
113
113
|
constraint: "multipleOf",
|
|
114
|
-
value:
|
|
114
|
+
value: multipleOf.toString()
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -120,11 +120,14 @@ const createConstraintsPredicate = (constraints) => (value) => {
|
|
|
120
120
|
if (value !== 0) {
|
|
121
121
|
return Result.err({
|
|
122
122
|
constraint: "step",
|
|
123
|
-
value:
|
|
123
|
+
value: step.toString()
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
126
|
} else if (value % step !== 0) {
|
|
127
|
-
return Result.err({
|
|
127
|
+
return Result.err({
|
|
128
|
+
constraint: "step",
|
|
129
|
+
value: step.toString()
|
|
130
|
+
});
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
return Result.ok(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number.mjs","sources":["../../src/primitives/number.mts"],"sourcesContent":["/* eslint-disable unicorn/no-negated-comparison */\nimport { Arr, expectType, Int, isNumber, Result } from 'ts-data-forge';\nimport {\n type BoolAnd,\n type BoolNot,\n type Brand,\n type FiniteNumber,\n type IsNever,\n type NegativeInt,\n type NonPositiveInt,\n type NonZeroFiniteNumber,\n type NonZeroInt,\n type PositiveInt,\n type SafeInt,\n type SafeUint,\n type StrictPick,\n type Uint,\n} from 'ts-type-forge';\nimport { refine } from '../other-types/index.mjs';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveType,\n type NumericConstraintViolation,\n} from '../utils/index.mjs';\n\ntype NumberType = number;\n\nexport function number(defaultValue?: NumberType): Type<NumberType>;\n\nexport function number<N extends NumberType, const C extends Constraints>(\n defaultValue: N & DefaultValueType<N, C>,\n constraints: C,\n): Type<ConstraintsToResultType<C>>;\n\nexport function number<C extends Constraints>(\n defaultValue: NumberType = 0,\n constraints?: C,\n): Type<NumberType> {\n const baseType = createPrimitiveType({\n typeName: 'number',\n defaultValue,\n is: isNumber,\n });\n\n if (constraints === undefined || Arr.isEmpty(Object.keys(constraints))) {\n return baseType;\n }\n\n const constraintsPredicate = createConstraintsPredicate(constraints);\n\n const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);\n\n if (Result.isErr(defaultValueConstraintsCheck)) {\n throw new Error(\n defaultValueErrorMessage(\n defaultValue,\n defaultValueConstraintsCheck.value,\n ),\n );\n }\n\n return refine({\n baseType,\n defaultValue,\n is: (value): value is NumberType =>\n Result.isOk(constraintsPredicate(value)),\n typeName: 'number',\n getConstraintDetails: (value) => {\n const result = constraintsPredicate(value);\n\n return Result.isErr(result)\n ? {\n kind: 'numeric-constraint',\n numericType: 'number',\n violation: result.value,\n }\n : undefined;\n },\n });\n}\n\ntype Constraints = Partial<\n Readonly<{\n finite: true;\n int: true;\n safeInteger: true;\n nonZero: true;\n negative: true;\n nonNegative: true;\n positive: true;\n nonPositive: true;\n\n gt: NumberType;\n gte: NumberType;\n min: NumberType;\n lt: NumberType;\n lte: NumberType;\n max: NumberType;\n multipleOf: NumberType;\n step: NumberType;\n }>\n>;\n\n/**\n * The set of constraints accepted by {@link number}.\n */\nexport type NumberTypeConstraints = Constraints;\n\n/**\n * The numeric-range subset of {@link NumberTypeConstraints}. These constraints\n * (`gt`, `gte`, `min`, `lt`, `lte`, `max`, `multipleOf`, `step`) add runtime\n * validation without changing the result brand, so the branded number types\n * under `predefined/brand/number` accept only this subset. To build a different\n * brand from a plain number, use {@link number} with the predicate constraints\n * instead, or the dedicated branded constructor for the target type.\n */\nexport type NumberRangeConstraints = StrictPick<\n NumberTypeConstraints,\n 'gt' | 'gte' | 'min' | 'lt' | 'lte' | 'max' | 'multipleOf' | 'step'\n>;\n\ntype DefaultValueType<\n N extends NumberType,\n C extends Constraints,\n> = DefaultValueWhenNonZeroIsOn<N, C> &\n DefaultValueWhenNegativeIsOn<N, C> &\n DefaultValueWhenNonNegativeIsOn<N, C> &\n DefaultValueWhenPositiveIsOn<N, C> &\n DefaultValueWhenNonPositiveIsOn<N, C>;\n\ntype ConstraintsToResultType<C extends Constraints> =\n ConstraintsToResultHelperType<ConstraintsToResultBrandKeys<C>>;\n\ntype ConstraintsToResultHelperType<\n R extends Readonly<{ brandKeys: string; brandFalseKeys: string }>,\n> =\n IsNever<R> extends true\n ? NumberType\n : Brand<NumberType, R['brandKeys'], R['brandFalseKeys']>;\n\ntype ConstraintsToResultBrandKeys<C extends Constraints> =\n | (C extends Readonly<{ int: true }>\n ? Readonly<{ brandKeys: 'Int' | 'Finite'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ safeInteger: true }>\n ? Readonly<{\n brandKeys: 'Finite' | 'Int' | 'SafeInt';\n brandFalseKeys: 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ finite: true }>\n ? Readonly<{ brandKeys: 'Finite'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ nonZero: true }>\n ? Readonly<{ brandKeys: '!=0'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ negative: true }>\n ? Readonly<{\n brandKeys: '!=0' | '< 2^15' | '< 2^16' | '< 2^31' | '< 2^32' | '<=0';\n brandFalseKeys: '>=0' | 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ nonNegative: true }>\n ? Readonly<{\n brandKeys: '>=0' | '> -2^16' | '> -2^32' | '>= -2^15' | '>= -2^31';\n brandFalseKeys: 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ positive: true }>\n ? Readonly<{\n brandKeys:\n '>=0' | '!=0' | '> -2^16' | '> -2^32' | '>= -2^15' | '>= -2^31';\n brandFalseKeys: '<=0' | 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ nonPositive: true }>\n ? Readonly<{\n brandKeys: '< 2^15' | '< 2^16' | '< 2^31' | '< 2^32' | '<=0';\n brandFalseKeys: 'NaNValue';\n }>\n : never);\n\n{\n type BrandKeysInt = ConstraintsToResultBrandKeys<Readonly<{ int: true }>>;\n\n expectType<BrandKeysInt['brandKeys'], 'Finite' | 'Int'>('=');\n\n expectType<BrandKeysInt['brandFalseKeys'], 'NaNValue'>('=');\n\n type BrandKeysPositiveInt = ConstraintsToResultBrandKeys<\n Readonly<{ int: true; positive: true }>\n >;\n\n expectType<\n BrandKeysPositiveInt['brandKeys'],\n | 'Int'\n | 'Finite'\n | '!=0'\n | '>=0'\n | '> -2^16'\n | '> -2^32'\n | '>= -2^15'\n | '>= -2^31'\n >('=');\n\n expectType<BrandKeysPositiveInt['brandFalseKeys'], '<=0' | 'NaNValue'>('=');\n\n expectType<ConstraintsToResultType<Readonly<{ finite: true }>>, FiniteNumber>(\n '=',\n );\n\n expectType<\n ConstraintsToResultType<Readonly<{ finite: true; nonZero: true }>>,\n NonZeroFiniteNumber\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonZero: true }>>,\n NonZeroInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; positive: true }>>,\n PositiveInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; negative: true }>>,\n NegativeInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonPositive: true }>>,\n NonPositiveInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonNegative: true }>>,\n Uint\n >('=');\n\n expectType<ConstraintsToResultType<Readonly<{ safeInteger: true }>>, SafeInt>(\n '=',\n );\n\n expectType<\n ConstraintsToResultType<Readonly<{ safeInteger: true; nonNegative: true }>>,\n SafeUint\n >('=');\n}\n\ntype DefaultValueWhenNonZeroIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ nonZero: true }> ? NonZeroNumber<N> : NumberType;\n\ntype DefaultValueWhenNegativeIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ negative: true }> ? NegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenNonNegativeIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonNegative: true }> ? NonNegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenPositiveIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ positive: true }> ? PositiveNumber<N> : NumberType;\n\ntype DefaultValueWhenNonPositiveIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonPositive: true }> ? NonPositiveNumber<N> : NumberType;\n\ntype NonZeroNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsZero<N> extends true\n ? never\n : N;\n\ntype NegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNegative<N> extends true\n ? N\n : never;\n\ntype NonNegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonNegative<N> extends true\n ? N\n : never;\n\ntype PositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsPositive<N> extends true\n ? N\n : never;\n\ntype NonPositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonPositive<N> extends true\n ? N\n : never;\n\ntype IsZero<N extends NumberType> = `${N}` extends '0' ? true : false;\n\ntype IsNonZero<N extends NumberType> = IsZero<N> extends true ? false : true;\n\ntype IsNegative<N extends NumberType> = `${N}` extends `-${string}`\n ? true\n : false;\n\ntype IsNonNegative<N extends NumberType> =\n IsNegative<N> extends true ? false : true;\n\ntype IsPositive<N extends NumberType> = BoolAnd<IsNonZero<N>, IsNonNegative<N>>;\n\ntype IsNonPositive<N extends NumberType> = BoolNot<IsPositive<N>>;\n\nconst createConstraintsPredicate =\n (constraints: Constraints) =>\n (value: NumberType): Result<true, NumericConstraintViolation> => {\n const {\n finite,\n int,\n safeInteger,\n nonZero,\n negative,\n nonNegative,\n positive,\n nonPositive,\n gt,\n gte,\n min,\n lt,\n lte,\n max,\n multipleOf,\n step,\n ..._rest\n } = constraints;\n\n expectType<keyof typeof _rest, never>('=');\n\n if (finite === true && !Number.isFinite(value)) {\n return Result.err({ constraint: 'finite', value: true } as const);\n }\n\n if (int === true && !Int.is(value)) {\n return Result.err({ constraint: 'int', value: true } as const);\n }\n\n if (safeInteger === true && !Number.isSafeInteger(value)) {\n return Result.err({ constraint: 'safeInteger', value: true } as const);\n }\n\n if (nonZero === true && !(value !== 0)) {\n return Result.err({ constraint: 'nonZero', value: true } as const);\n }\n\n if (negative === true && !(value < 0)) {\n return Result.err({ constraint: 'negative', value: true } as const);\n }\n\n if (nonNegative === true && !(value >= 0)) {\n return Result.err({ constraint: 'nonNegative', value: true } as const);\n }\n\n if (positive === true && !(value > 0)) {\n return Result.err({ constraint: 'positive', value: true } as const);\n }\n\n if (nonPositive === true && !(value <= 0)) {\n return Result.err({ constraint: 'nonPositive', value: true } as const);\n }\n\n if (gt !== undefined && !(value > gt)) {\n return Result.err({ constraint: 'gt', value: String(gt) } as const);\n }\n\n if (gte !== undefined && !(value >= gte)) {\n return Result.err({ constraint: 'gte', value: String(gte) } as const);\n }\n\n if (min !== undefined && !(value >= min)) {\n return Result.err({ constraint: 'min', value: String(min) } as const);\n }\n\n if (lt !== undefined && !(value < lt)) {\n return Result.err({ constraint: 'lt', value: String(lt) } as const);\n }\n\n if (lte !== undefined && !(value <= lte)) {\n return Result.err({ constraint: 'lte', value: String(lte) } as const);\n }\n\n if (max !== undefined && !(value <= max)) {\n return Result.err({ constraint: 'max', value: String(max) } as const);\n }\n\n // `value % 0` throws a RangeError, so the zero divisor is handled\n // separately: it only admits zero.\n if (multipleOf !== undefined) {\n if (multipleOf === 0) {\n if (value !== 0) {\n return Result.err({\n constraint: 'multipleOf',\n value: String(multipleOf),\n } as const);\n }\n } else if (value % multipleOf !== 0) {\n return Result.err({\n constraint: 'multipleOf',\n value: String(multipleOf),\n } as const);\n }\n }\n\n if (step !== undefined) {\n if (step === 0) {\n if (value !== 0) {\n return Result.err({\n constraint: 'step',\n value: String(step),\n } as const);\n }\n } else if (value % step !== 0) {\n return Result.err({ constraint: 'step', value: String(step) } as const);\n }\n }\n\n return Result.ok(true);\n };\n\nconst defaultValueErrorMessage = (\n value: NumberType,\n violation: NumericConstraintViolation,\n): string =>\n `defaultValue [${value}] for number does not satisfy the constraint ${violation.constraint} = ${violation.value}` as const;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"number.mjs","sources":["../../src/primitives/number.mts"],"sourcesContent":["/* eslint-disable unicorn/no-negated-comparison */\nimport { Arr, expectType, Int, isNumber, Result } from 'ts-data-forge';\nimport {\n type BoolAnd,\n type BoolNot,\n type Brand,\n type FiniteNumber,\n type IsNever,\n type NegativeInt,\n type NonPositiveInt,\n type NonZeroFiniteNumber,\n type NonZeroInt,\n type PositiveInt,\n type SafeInt,\n type SafeUint,\n type StrictPick,\n type Uint,\n} from 'ts-type-forge';\nimport { refine } from '../other-types/index.mjs';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveType,\n type NumericConstraintViolation,\n} from '../utils/index.mjs';\n\ntype NumberType = number;\n\nexport function number(defaultValue?: NumberType): Type<NumberType>;\n\nexport function number<N extends NumberType, const C extends Constraints>(\n defaultValue: N & DefaultValueType<N, C>,\n constraints: C,\n): Type<ConstraintsToResultType<C>>;\n\nexport function number<C extends Constraints>(\n defaultValue: NumberType = 0,\n constraints?: C,\n): Type<NumberType> {\n const baseType = createPrimitiveType({\n typeName: 'number',\n defaultValue,\n is: isNumber,\n });\n\n if (constraints === undefined || Arr.isEmpty(Object.keys(constraints))) {\n return baseType;\n }\n\n const constraintsPredicate = createConstraintsPredicate(constraints);\n\n const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);\n\n if (Result.isErr(defaultValueConstraintsCheck)) {\n throw new Error(\n defaultValueErrorMessage(\n defaultValue,\n defaultValueConstraintsCheck.value,\n ),\n );\n }\n\n return refine({\n baseType,\n defaultValue,\n is: (value): value is NumberType =>\n Result.isOk(constraintsPredicate(value)),\n typeName: 'number',\n getConstraintDetails: (value) => {\n const result = constraintsPredicate(value);\n\n return Result.isErr(result)\n ? {\n kind: 'numeric-constraint',\n numericType: 'number',\n violation: result.value,\n }\n : undefined;\n },\n });\n}\n\ntype Constraints = Partial<\n Readonly<{\n finite: true;\n int: true;\n safeInteger: true;\n nonZero: true;\n negative: true;\n nonNegative: true;\n positive: true;\n nonPositive: true;\n\n gt: NumberType;\n gte: NumberType;\n min: NumberType;\n lt: NumberType;\n lte: NumberType;\n max: NumberType;\n multipleOf: NumberType;\n step: NumberType;\n }>\n>;\n\n/**\n * The set of constraints accepted by {@link number}.\n */\nexport type NumberTypeConstraints = Constraints;\n\n/**\n * The numeric-range subset of {@link NumberTypeConstraints}. These constraints\n * (`gt`, `gte`, `min`, `lt`, `lte`, `max`, `multipleOf`, `step`) add runtime\n * validation without changing the result brand, so the branded number types\n * under `predefined/brand/number` accept only this subset. To build a different\n * brand from a plain number, use {@link number} with the predicate constraints\n * instead, or the dedicated branded constructor for the target type.\n */\nexport type NumberRangeConstraints = StrictPick<\n NumberTypeConstraints,\n 'gt' | 'gte' | 'min' | 'lt' | 'lte' | 'max' | 'multipleOf' | 'step'\n>;\n\ntype DefaultValueType<\n N extends NumberType,\n C extends Constraints,\n> = DefaultValueWhenNonZeroIsOn<N, C> &\n DefaultValueWhenNegativeIsOn<N, C> &\n DefaultValueWhenNonNegativeIsOn<N, C> &\n DefaultValueWhenPositiveIsOn<N, C> &\n DefaultValueWhenNonPositiveIsOn<N, C>;\n\ntype ConstraintsToResultType<C extends Constraints> =\n ConstraintsToResultHelperType<ConstraintsToResultBrandKeys<C>>;\n\ntype ConstraintsToResultHelperType<\n R extends Readonly<{ brandKeys: string; brandFalseKeys: string }>,\n> =\n IsNever<R> extends true\n ? NumberType\n : Brand<NumberType, R['brandKeys'], R['brandFalseKeys']>;\n\ntype ConstraintsToResultBrandKeys<C extends Constraints> =\n | (C extends Readonly<{ int: true }>\n ? Readonly<{ brandKeys: 'Int' | 'Finite'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ safeInteger: true }>\n ? Readonly<{\n brandKeys: 'Finite' | 'Int' | 'SafeInt';\n brandFalseKeys: 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ finite: true }>\n ? Readonly<{ brandKeys: 'Finite'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ nonZero: true }>\n ? Readonly<{ brandKeys: '!=0'; brandFalseKeys: 'NaNValue' }>\n : never)\n | (C extends Readonly<{ negative: true }>\n ? Readonly<{\n brandKeys: '!=0' | '< 2^15' | '< 2^16' | '< 2^31' | '< 2^32' | '<=0';\n brandFalseKeys: '>=0' | 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ nonNegative: true }>\n ? Readonly<{\n brandKeys: '>=0' | '> -2^16' | '> -2^32' | '>= -2^15' | '>= -2^31';\n brandFalseKeys: 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ positive: true }>\n ? Readonly<{\n brandKeys:\n '>=0' | '!=0' | '> -2^16' | '> -2^32' | '>= -2^15' | '>= -2^31';\n brandFalseKeys: '<=0' | 'NaNValue';\n }>\n : never)\n | (C extends Readonly<{ nonPositive: true }>\n ? Readonly<{\n brandKeys: '< 2^15' | '< 2^16' | '< 2^31' | '< 2^32' | '<=0';\n brandFalseKeys: 'NaNValue';\n }>\n : never);\n\n{\n type BrandKeysInt = ConstraintsToResultBrandKeys<Readonly<{ int: true }>>;\n\n expectType<BrandKeysInt['brandKeys'], 'Finite' | 'Int'>('=');\n\n expectType<BrandKeysInt['brandFalseKeys'], 'NaNValue'>('=');\n\n type BrandKeysPositiveInt = ConstraintsToResultBrandKeys<\n Readonly<{ int: true; positive: true }>\n >;\n\n expectType<\n BrandKeysPositiveInt['brandKeys'],\n | 'Int'\n | 'Finite'\n | '!=0'\n | '>=0'\n | '> -2^16'\n | '> -2^32'\n | '>= -2^15'\n | '>= -2^31'\n >('=');\n\n expectType<BrandKeysPositiveInt['brandFalseKeys'], '<=0' | 'NaNValue'>('=');\n\n expectType<ConstraintsToResultType<Readonly<{ finite: true }>>, FiniteNumber>(\n '=',\n );\n\n expectType<\n ConstraintsToResultType<Readonly<{ finite: true; nonZero: true }>>,\n NonZeroFiniteNumber\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonZero: true }>>,\n NonZeroInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; positive: true }>>,\n PositiveInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; negative: true }>>,\n NegativeInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonPositive: true }>>,\n NonPositiveInt\n >('=');\n\n expectType<\n ConstraintsToResultType<Readonly<{ int: true; nonNegative: true }>>,\n Uint\n >('=');\n\n expectType<ConstraintsToResultType<Readonly<{ safeInteger: true }>>, SafeInt>(\n '=',\n );\n\n expectType<\n ConstraintsToResultType<Readonly<{ safeInteger: true; nonNegative: true }>>,\n SafeUint\n >('=');\n}\n\ntype DefaultValueWhenNonZeroIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ nonZero: true }> ? NonZeroNumber<N> : NumberType;\n\ntype DefaultValueWhenNegativeIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ negative: true }> ? NegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenNonNegativeIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonNegative: true }> ? NonNegativeNumber<N> : NumberType;\n\ntype DefaultValueWhenPositiveIsOn<N extends NumberType, C extends Constraints> =\n C extends Readonly<{ positive: true }> ? PositiveNumber<N> : NumberType;\n\ntype DefaultValueWhenNonPositiveIsOn<\n N extends NumberType,\n C extends Constraints,\n> =\n C extends Readonly<{ nonPositive: true }> ? NonPositiveNumber<N> : NumberType;\n\ntype NonZeroNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsZero<N> extends true\n ? never\n : N;\n\ntype NegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNegative<N> extends true\n ? N\n : never;\n\ntype NonNegativeNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonNegative<N> extends true\n ? N\n : never;\n\ntype PositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsPositive<N> extends true\n ? N\n : never;\n\ntype NonPositiveNumber<N extends NumberType> = NumberType extends N\n ? NumberType\n : IsNonPositive<N> extends true\n ? N\n : never;\n\ntype IsZero<N extends NumberType> = `${N}` extends '0' ? true : false;\n\ntype IsNonZero<N extends NumberType> = IsZero<N> extends true ? false : true;\n\ntype IsNegative<N extends NumberType> = `${N}` extends `-${string}`\n ? true\n : false;\n\ntype IsNonNegative<N extends NumberType> =\n IsNegative<N> extends true ? false : true;\n\ntype IsPositive<N extends NumberType> = BoolAnd<IsNonZero<N>, IsNonNegative<N>>;\n\ntype IsNonPositive<N extends NumberType> = BoolNot<IsPositive<N>>;\n\nconst createConstraintsPredicate =\n (constraints: Constraints) =>\n (value: NumberType): Result<true, NumericConstraintViolation> => {\n const {\n finite,\n int,\n safeInteger,\n nonZero,\n negative,\n nonNegative,\n positive,\n nonPositive,\n gt,\n gte,\n min,\n lt,\n lte,\n max,\n multipleOf,\n step,\n ..._rest\n } = constraints;\n\n expectType<keyof typeof _rest, never>('=');\n\n if (finite === true && !Number.isFinite(value)) {\n return Result.err({ constraint: 'finite', value: true } as const);\n }\n\n if (int === true && !Int.is(value)) {\n return Result.err({ constraint: 'int', value: true } as const);\n }\n\n if (safeInteger === true && !Number.isSafeInteger(value)) {\n return Result.err({ constraint: 'safeInteger', value: true } as const);\n }\n\n if (nonZero === true && !(value !== 0)) {\n return Result.err({ constraint: 'nonZero', value: true } as const);\n }\n\n if (negative === true && !(value < 0)) {\n return Result.err({ constraint: 'negative', value: true } as const);\n }\n\n if (nonNegative === true && !(value >= 0)) {\n return Result.err({ constraint: 'nonNegative', value: true } as const);\n }\n\n if (positive === true && !(value > 0)) {\n return Result.err({ constraint: 'positive', value: true } as const);\n }\n\n if (nonPositive === true && !(value <= 0)) {\n return Result.err({ constraint: 'nonPositive', value: true } as const);\n }\n\n if (gt !== undefined && !(value > gt)) {\n return Result.err({ constraint: 'gt', value: gt.toString() } as const);\n }\n\n if (gte !== undefined && !(value >= gte)) {\n return Result.err({ constraint: 'gte', value: gte.toString() } as const);\n }\n\n if (min !== undefined && !(value >= min)) {\n return Result.err({ constraint: 'min', value: min.toString() } as const);\n }\n\n if (lt !== undefined && !(value < lt)) {\n return Result.err({ constraint: 'lt', value: lt.toString() } as const);\n }\n\n if (lte !== undefined && !(value <= lte)) {\n return Result.err({ constraint: 'lte', value: lte.toString() } as const);\n }\n\n if (max !== undefined && !(value <= max)) {\n return Result.err({ constraint: 'max', value: max.toString() } as const);\n }\n\n // `value % 0` throws a RangeError, so the zero divisor is handled\n // separately: it only admits zero.\n if (multipleOf !== undefined) {\n if (multipleOf === 0) {\n if (value !== 0) {\n return Result.err({\n constraint: 'multipleOf',\n value: multipleOf.toString(),\n } as const);\n }\n } else if (value % multipleOf !== 0) {\n return Result.err({\n constraint: 'multipleOf',\n value: multipleOf.toString(),\n } as const);\n }\n }\n\n if (step !== undefined) {\n if (step === 0) {\n if (value !== 0) {\n return Result.err({\n constraint: 'step',\n value: step.toString(),\n } as const);\n }\n } else if (value % step !== 0) {\n return Result.err({\n constraint: 'step',\n value: step.toString(),\n } as const);\n }\n }\n\n return Result.ok(true);\n };\n\nconst defaultValueErrorMessage = (\n value: NumberType,\n violation: NumericConstraintViolation,\n): string =>\n `defaultValue [${value}] for number does not satisfy the constraint ${violation.constraint} = ${violation.value}` as const;\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial.d.mts","sourceRoot":"","sources":["../../src/record/partial.mts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,IAAI,EAKV,MAAM,aAAa,CAAC;AAKrB;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,KAAK,CAAC,CAAC,SAAS,aAAa,EAC7B,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,cAElD,IAAI,CAAC,CAAC,CAAC,YACT,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;CACtC,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,EACL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,IAAI,EAKV,MAAM,aAAa,CAAC;AAKrB;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,KAAK,CAAC,CAAC,SAAS,aAAa,EAC7B,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,cAElD,IAAI,CAAC,CAAC,CAAC,YACT,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC,CACH,KACA,WAAW,CAAC,CAAC,EAAE,gBAAgB,CAkCjC,CAAC;AAEF,KAAK,WAAW,CACd,CAAC,SAAS,aAAa,EACvB,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,GAClE,SAAS,IACT,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE5C,sCAAsC;AACtC,KAAK,YAAY,CACf,CAAC,SAAS,aAAa,EACvB,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,IAEpE,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,SAAS,IAAI,GAC5C,OAAO,CAAC,CAAC,CAAC,GACV,gBAAgB,CAAC,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC"}
|
package/dist/record/partial.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 'ts-data-forge';
|
|
1
|
+
import { Obj } from 'ts-data-forge';
|
|
2
2
|
import { hasRecordInternals, flattenShapeStructure } from '../type.mjs';
|
|
3
3
|
import '@sindresorhus/is';
|
|
4
4
|
import { toUnionKeyString } from '../utils/to-union-string.mjs';
|
|
@@ -21,10 +21,9 @@ const partial = (recordType, options) => {
|
|
|
21
21
|
const keysToBeOptional = new Set(
|
|
22
22
|
options?.keysToBeOptional ?? Object.keys(shape)
|
|
23
23
|
);
|
|
24
|
-
const partialShape =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
24
|
+
const partialShape = Obj.map(
|
|
25
|
+
shape,
|
|
26
|
+
(v, k) => keysToBeOptional.has(k) ? optional(v) : v
|
|
28
27
|
);
|
|
29
28
|
return record(partialShape, {
|
|
30
29
|
typeName: typeNameFilled,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial.mjs","sources":["../../src/record/partial.mts"],"sourcesContent":["import { expectType } from 'ts-data-forge';\nimport {\n type ArrayElement,\n type NonEmptyTuple,\n type PartiallyPartial,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n type ExcessPropertyOption,\n type Type,\n type TypeOf,\n type UnknownShape,\n flattenShapeStructure,\n hasRecordInternals,\n} from '../type.mjs';\nimport { toUnionKeyString } from '../utils/index.mjs';\nimport { optional } from './optional.mjs';\nimport { record } from './record.mjs';\n\n/**\n * Creates a Partial type. If keysToBeOptional is set, only those keys are\n * optional, otherwise, all properties are optional.\n */\nexport const partial = <\n const R extends UnknownRecord,\n const KeysToBeOptional extends NonEmptyTuple<keyof R & string>,\n>(\n recordType: Type<R>,\n options?: Partial<\n Readonly<{\n keysToBeOptional: KeysToBeOptional;\n typeName: string;\n excessProperty: ExcessPropertyOption;\n }>\n >,\n): PartialType<R, KeysToBeOptional> => {\n if (!hasRecordInternals(recordType)) {\n throw new Error(\n `Expected a record type but received: ${recordType.typeName}`,\n );\n }\n\n const shape = flattenShapeStructure(recordType.shapeStructure);\n\n if (shape === undefined) {\n throw new Error(\n `partial() requires a simple or intersection record type, but received a union type`,\n );\n }\n\n const typeNameFilled: string =\n options?.typeName ??\n (options?.keysToBeOptional === undefined\n ? `Partial<${recordType.typeName}>`\n : `PartiallyPartial<${recordType.typeName}, ${toUnionKeyString(options.keysToBeOptional)}>`);\n\n const keysToBeOptional: ReadonlySet<string> = new Set(\n options?.keysToBeOptional ?? Object.keys(shape),\n );\n\n const partialShape =
|
|
1
|
+
{"version":3,"file":"partial.mjs","sources":["../../src/record/partial.mts"],"sourcesContent":["import { Obj, expectType } from 'ts-data-forge';\nimport {\n type ArrayElement,\n type NonEmptyTuple,\n type PartiallyPartial,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n type ExcessPropertyOption,\n type Type,\n type TypeOf,\n type UnknownShape,\n flattenShapeStructure,\n hasRecordInternals,\n} from '../type.mjs';\nimport { toUnionKeyString } from '../utils/index.mjs';\nimport { optional } from './optional.mjs';\nimport { record } from './record.mjs';\n\n/**\n * Creates a Partial type. If keysToBeOptional is set, only those keys are\n * optional, otherwise, all properties are optional.\n */\nexport const partial = <\n const R extends UnknownRecord,\n const KeysToBeOptional extends NonEmptyTuple<keyof R & string>,\n>(\n recordType: Type<R>,\n options?: Partial<\n Readonly<{\n keysToBeOptional: KeysToBeOptional;\n typeName: string;\n excessProperty: ExcessPropertyOption;\n }>\n >,\n): PartialType<R, KeysToBeOptional> => {\n if (!hasRecordInternals(recordType)) {\n throw new Error(\n `Expected a record type but received: ${recordType.typeName}`,\n );\n }\n\n const shape = flattenShapeStructure(recordType.shapeStructure);\n\n if (shape === undefined) {\n throw new Error(\n `partial() requires a simple or intersection record type, but received a union type`,\n );\n }\n\n const typeNameFilled: string =\n options?.typeName ??\n (options?.keysToBeOptional === undefined\n ? `Partial<${recordType.typeName}>`\n : `PartiallyPartial<${recordType.typeName}, ${toUnionKeyString(options.keysToBeOptional)}>`);\n\n const keysToBeOptional: ReadonlySet<string> = new Set(\n options?.keysToBeOptional ?? Object.keys(shape),\n );\n\n const partialShape = Obj.map(shape, (v, k) =>\n keysToBeOptional.has(k) ? optional(v) : v,\n ) satisfies UnknownShape;\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return record(partialShape, {\n typeName: typeNameFilled,\n excessProperty: options?.excessProperty ?? recordType.excessProperty,\n }) as unknown as PartialType<R, KeysToBeOptional>;\n};\n\ntype PartialType<\n R extends UnknownRecord,\n KeysToBeOptional extends NonEmptyTuple<keyof R & string> | undefined =\n undefined,\n> = Type<PartialValue<R, KeysToBeOptional>>;\n\n/** Compute the partial value type. */\ntype PartialValue<\n R extends UnknownRecord,\n KeysToBeOptional extends NonEmptyTuple<keyof R & string> | undefined,\n> =\n TypeEq<KeysToBeOptional, undefined> extends true\n ? Partial<R>\n : PartiallyPartial<R, ArrayElement<KeysToBeOptional>>;\n\n// --- expectType assertions ---\n\n{\n type Base = ReturnType<\n typeof record<Readonly<{ a: Type<0>; b: Type<1>; c: Type<2> }>>\n >;\n\n expectType<\n PartialType<TypeOf<Base>, readonly ['a', 'b', 'c']>,\n Type<Partial<Readonly<{ a: 0; b: 1; c: 2 }>>>\n >('=');\n\n expectType<\n PartialType<TypeOf<Base>, readonly ['a', 'b']>,\n Type<Readonly<{ a?: 0; b?: 1; c: 2 }>>\n >('=');\n\n expectType<\n // @ts-expect-error NonEmptyTuple is required if keysToBeOptional is provided\n PartialType<TypeOf<Base>, readonly []>,\n Type<Readonly<{ a?: 0; b?: 1; c: 2 }>>\n >('!=');\n\n expectType<\n PartialType<TypeOf<Base>>,\n Type<Readonly<{ a?: 0; b?: 1; c?: 2 }>>\n >('=');\n\n // partial with no keys makes all properties optional\n expectType<\n TypeOf<\n ReturnType<typeof partial<TypeOf<Base>, NonEmptyTuple<'a' | 'b' | 'c'>>>\n >,\n Partial<Readonly<{ a: 0; b: 1; c: 2 }>>\n >('=');\n}\n"],"names":[],"mappings":";;;;;;;MAwBa,OAAA,GAAU,CAIrB,UAAA,EACA,OAAA,KAOqC;AACrC,EAAA,IAAI,CAAC,kBAAA,CAAmB,UAAU,CAAA,EAAG;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qCAAA,EAAwC,WAAW,QAAQ,CAAA;AAAA,KAC7D;AAAA,EAAA;AAGF,EAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,UAAA,CAAW,cAAc,CAAA;AAE7D,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kFAAA;AAAA,KACF;AAAA,EAAA;AAGF,EAAA,MAAM,iBACJ,OAAA,EAAS,QAAA,KACR,OAAA,EAAS,gBAAA,KAAqB,SAC3B,CAAA,QAAA,EAAW,UAAA,CAAW,QAAQ,CAAA,CAAA,CAAA,GAC9B,oBAAoB,UAAA,CAAW,QAAQ,KAAK,gBAAA,CAAiB,OAAA,CAAQ,gBAAgB,CAAC,CAAA,CAAA,CAAA,CAAA;AAE5F,EAAA,MAAM,mBAAwC,IAAI,GAAA;AAAA,IAChD,OAAA,EAAS,gBAAA,IAAoB,MAAA,CAAO,IAAA,CAAK,KAAK;AAAA,GAChD;AAEA,EAAA,MAAM,eAAe,GAAA,CAAI,GAAA;AAAA,IAAI,KAAA;AAAA,IAAO,CAAC,GAAG,CAAA,KACtC,gBAAA,CAAiB,IAAI,CAAC,CAAA,GAAI,QAAA,CAAS,CAAC,CAAA,GAAI;AAAA,GAC1C;AAGA,EAAA,OAAO,OAAO,YAAA,EAAc;AAAA,IAC1B,QAAA,EAAU,cAAA;AAAA,IACV,cAAA,EAAgB,OAAA,EAAS,cAAA,IAAkB,UAAA,CAAW;AAAA,GACvD,CAAA;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.d.mts","sourceRoot":"","sources":["../../src/record/record.mts"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,oBAAoB,EAEzB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAUrB,eAAO,MAAM,MAAM,GACjB,KAAK,CAAC,CAAC,SAAS,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,oBAAoB,GAAG,OAAO,SAExC,CAAC,YACE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,cAAc,EAAE,EAAE,CAAC;CACpB,CAAC,CACH,KACA,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"record.d.mts","sourceRoot":"","sources":["../../src/record/record.mts"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,oBAAoB,EAEzB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAUrB,eAAO,MAAM,MAAM,GACjB,KAAK,CAAC,CAAC,SAAS,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,oBAAoB,GAAG,OAAO,SAExC,CAAC,YACE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,cAAc,EAAE,EAAE,CAAC;CACpB,CAAC,CACH,KACA,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CA4K7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,CAAC,CAAC,SAAS,YAAY,SAChD,CAAC,YACE,OAAO,CAAC,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,KAChD,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAI1B,CAAC;AAML,gBAAgB;AAChB,KAAK,mBAAmB,CAAC,CAAC,SAAS,YAAY,IAC7C,kBAAkB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;AAEhD,kBAAU,kBAAkB,CAAC;IAC3B,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,YAAY,IACxD,0BAA0B,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD,KAAK,0BAA0B,CAC7B,CAAC,SAAS,YAAY,EACtB,YAAY,SAAS,MAAM,CAAC,IAE5B,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,IAAI,GACpC,QAAQ,CAAC;SACN,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KAC9D,CAAC,GACF,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,SAAS,IAAI,GACxC,iBAAiB,CACf,QAAQ,CAAC;SAAG,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KAAE,CAAC,CACrD,GACD,iBAAiB,CACf,QAAQ,CACN;SAAG,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KAAE,GAAG;SAC1C,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KAC9D,CACF,CACF,CAAC;IAEV,KAAK,gBAAgB,CAAC,CAAC,SAAS,YAAY,IAAI;SAC7C,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC;YAAE,QAAQ,EAAE,IAAI,CAAA;SAAE,CAAC,GAAG,CAAC,GAAG,KAAK;KACtE,CAAC,MAAM,CAAC,CAAC,CAAC;;CACZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.mjs","sources":["../../src/record/record.mts"],"sourcesContent":["import {\n Arr,\n expectType,\n hasKey,\n isRecord,\n memoizeFunction,\n Obj,\n Optional,\n Result,\n tp,\n} from 'ts-data-forge';\nimport {\n type MergeIntersection,\n type StrictExclude,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n type ExcessPropertyOption,\n type RecordTypeInternals,\n type Type,\n type TypeOf,\n type UnknownShape,\n} from '../type.mjs';\nimport {\n createAssertFn,\n createCastFn,\n createIsFn,\n createPrimitiveValidationError,\n prependPathToValidationErrors,\n type ValidationError,\n} from '../utils/index.mjs';\n\nexport const record = <\n const S extends UnknownShape,\n const EP extends ExcessPropertyOption = 'allow',\n>(\n shape: S,\n options?: Partial<\n Readonly<{\n typeName: string;\n\n /**\n * Controls how excess properties (keys not in shape) are handled.\n *\n * - `'allow'` (default) — accept excess properties\n * - `'reject'` — reject objects with excess properties\n */\n excessProperty: EP;\n }>\n >,\n): Type<RecordTypeFromShape<S>> => {\n type V = RecordTypeFromShape<S>;\n\n const sourceKeys = new Set(Object.keys(shape));\n\n const typeNameFilled: string =\n options?.typeName ??\n `{ ${Object.entries(shape)\n .map(([k, v]) => `${k}: ${v.typeName}`)\n .join(', ')} }`;\n\n const ep: ExcessPropertyOption = options?.excessProperty ?? 'allow';\n\n const getDefaultValue = memoizeFunction(\n (): V =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Object.fromEntries(\n Object.entries(shape).map(([key, value]) =>\n tp(key, value.defaultValue),\n ),\n ) as V,\n );\n\n const validate: Type<V>['validate'] = (a) => {\n if (!isRecord(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'record',\n typeName: typeNameFilled,\n details: undefined,\n }),\n ]);\n }\n\n const defaultErrors: readonly ValidationError[] = Arr.generate(\n function* () {\n for (const [k, valueType] of Object.entries(shape)) {\n if (!hasKey(a, k)) {\n if (shape[k]?.optional !== true) {\n yield {\n path: [k],\n actualValue: a,\n typeName: typeNameFilled,\n expectedType: typeNameFilled,\n details: {\n kind: 'missing-key',\n key: k,\n },\n } satisfies ValidationError;\n }\n } else {\n // The case where the key exists in the object\n const v = a[k];\n\n // Skip validation for optional fields with undefined values\n if (v === undefined && valueType.optional === true) {\n continue;\n }\n\n const res = valueType.validate(v);\n\n if (Result.isErr(res)) {\n yield* prependPathToValidationErrors(res.value, k);\n }\n }\n }\n },\n );\n\n if (ep === 'reject') {\n const excessKeys = Object.keys(a).filter((key) => !sourceKeys.has(key));\n\n const excessErrors: readonly ValidationError[] = excessKeys.map(\n (key) =>\n ({\n path: [key],\n actualValue: a[key],\n typeName: typeNameFilled,\n expectedType: typeNameFilled,\n details: {\n kind: 'excess-key',\n key,\n },\n }) satisfies ValidationError,\n );\n\n // Combine all errors\n const allErrors = [...defaultErrors, ...excessErrors] as const;\n\n return Arr.isNonEmpty(allErrors)\n ? Result.err(allErrors)\n : // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Result.ok(a as V);\n }\n\n // ep === 'allow'\n return Arr.isNonEmpty(defaultErrors)\n ? Result.err(defaultErrors)\n : // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Result.ok(a as V);\n };\n\n const fill = (a: unknown): V => {\n if (!isRecord(a)) {\n return getDefaultValue();\n }\n\n // fill always produces shape-only values (strips excess)\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Object.fromEntries(\n Object.entries(shape).map(([k, v]) => {\n if (hasKey(a, k)) {\n const value = a[k];\n\n // For optional fields, if the value is undefined, keep it as undefined\n if (value === undefined && v.optional === true) {\n return tp(k, undefined);\n }\n\n return tp(k, v.fill(value));\n }\n\n return tp(k, v.defaultValue);\n }),\n ) as V;\n };\n\n const prune = (a: V): V => {\n // The input is statically guaranteed to be a record.\n const rec: UnknownRecord = a;\n\n // prune keeps only the value paths represented by the shape;\n // unlike fill, it never fills in missing keys with default values\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Obj.filterMap(shape, (v, k) => {\n // Only optional keys can be absent in the input; required keys are\n // statically guaranteed to be present.\n if (v.optional === true) {\n if (!hasKey(rec, k)) {\n return Optional.none;\n }\n\n // For optional fields, if the value is undefined, keep it as undefined\n if (rec[k] === undefined) {\n return Optional.some(undefined);\n }\n }\n\n return Optional.some(v.prune(rec[k]));\n }) as V;\n };\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return {\n typeName: typeNameFilled,\n get defaultValue() {\n return getDefaultValue();\n },\n fill,\n prune,\n validate,\n is: createIsFn(validate),\n assertIs: createAssertFn(validate),\n cast: createCastFn(validate),\n shapeStructure: { kind: 'simple', shape } as const,\n excessProperty: ep,\n } satisfies Type<V> & RecordTypeInternals as Type<V>;\n};\n\n/**\n * Creates a strict record type that rejects excess properties.\n * This is an alias for `record(shape, { excessProperty: 'reject' })`.\n */\nexport const strictRecord = <const S extends UnknownShape>(\n shape: S,\n options?: Partial<Readonly<{ typeName: string }>>,\n): Type<RecordTypeFromShape<S>> =>\n record(shape, {\n typeName: options?.typeName,\n excessProperty: 'reject',\n });\n\n// ---------------------------------------------------------------------------\n// RecordTypeValue (internal — computes value type from shape)\n// ---------------------------------------------------------------------------\n\n/** @internal */\ntype RecordTypeFromShape<S extends UnknownShape> =\n TsFortressInternal.RecordTypeFromShapeImpl<S>;\n\nnamespace TsFortressInternal {\n export type RecordTypeFromShapeImpl<S extends UnknownShape> =\n RecordTypeFromShapeImplSub<S, OptionalTypeKeys<S>>;\n\n type RecordTypeFromShapeImplSub<\n S extends UnknownShape,\n OptionalKeys extends keyof S,\n > =\n TypeEq<OptionalKeys, never> extends true\n ? Readonly<{\n [key in StrictExclude<keyof S, OptionalKeys>]: TypeOf<S[key]>;\n }>\n : TypeEq<keyof S, OptionalKeys> extends true\n ? MergeIntersection<\n Readonly<{ [key in OptionalKeys]?: TypeOf<S[key]> }>\n >\n : MergeIntersection<\n Readonly<\n { [key in OptionalKeys]?: TypeOf<S[key]> } & {\n [key in StrictExclude<keyof S, OptionalKeys>]: TypeOf<S[key]>;\n }\n >\n >;\n\n type OptionalTypeKeys<S extends UnknownShape> = {\n [K in keyof S]: S[K] extends Readonly<{ optional: true }> ? K : never;\n }[keyof S];\n}\n\n// --- expectType assertions ---\n\nexpectType<\n RecordTypeFromShape<Readonly<{ a: Type<0>; b: Type<1>; c: Type<2> }>>,\n Readonly<{ a: 0; b: 1; c: 2 }>\n>('=');\n\nexpectType<\n Type<RecordTypeFromShape<Readonly<{ a: Type<0> }>>>,\n Type<Readonly<{ a: 0 }>>\n>('=');\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"record.mjs","sources":["../../src/record/record.mts"],"sourcesContent":["import {\n Arr,\n expectType,\n hasKey,\n isRecord,\n memoizeFunction,\n Obj,\n Optional,\n Result,\n tp,\n} from 'ts-data-forge';\nimport {\n type MergeIntersection,\n type StrictExclude,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n type ExcessPropertyOption,\n type RecordTypeInternals,\n type Type,\n type TypeOf,\n type UnknownShape,\n} from '../type.mjs';\nimport {\n createAssertFn,\n createCastFn,\n createIsFn,\n createPrimitiveValidationError,\n prependPathToValidationErrors,\n type ValidationError,\n} from '../utils/index.mjs';\n\nexport const record = <\n const S extends UnknownShape,\n const EP extends ExcessPropertyOption = 'allow',\n>(\n shape: S,\n options?: Partial<\n Readonly<{\n typeName: string;\n\n /**\n * Controls how excess properties (keys not in shape) are handled.\n *\n * - `'allow'` (default) — accept excess properties\n * - `'reject'` — reject objects with excess properties\n */\n excessProperty: EP;\n }>\n >,\n): Type<RecordTypeFromShape<S>> => {\n type V = RecordTypeFromShape<S>;\n\n // Annotated rather than inferred: the strict standard library types\n // `Object.keys` as the record's own key union, which would make `has` reject\n // the plain `string` keys read back off the value being validated. The\n // membership test is the point here, so the wider element type is correct.\n const sourceKeys: ReadonlySet<string> = new Set(Object.keys(shape));\n\n const typeNameFilled: string =\n options?.typeName ??\n `{ ${Object.entries(shape)\n .map(([k, v]) => `${k}: ${v.typeName}`)\n .join(', ')} }`;\n\n const ep: ExcessPropertyOption = options?.excessProperty ?? 'allow';\n\n const getDefaultValue = memoizeFunction(\n (): V =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Object.fromEntries(\n Object.entries(shape).map(([key, value]) =>\n tp(key, value.defaultValue),\n ),\n ) as V,\n );\n\n const validate: Type<V>['validate'] = (a) => {\n if (!isRecord(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'record',\n typeName: typeNameFilled,\n details: undefined,\n }),\n ]);\n }\n\n const defaultErrors: readonly ValidationError[] = Arr.generate(\n function* () {\n for (const [k, valueType] of Object.entries(shape)) {\n if (!hasKey(a, k)) {\n if (shape[k]?.optional !== true) {\n yield {\n path: [k],\n actualValue: a,\n typeName: typeNameFilled,\n expectedType: typeNameFilled,\n details: {\n kind: 'missing-key',\n key: k,\n },\n } satisfies ValidationError;\n }\n } else {\n // The case where the key exists in the object\n const v = a[k];\n\n // Skip validation for optional fields with undefined values\n if (v === undefined && valueType.optional === true) {\n continue;\n }\n\n const res = valueType.validate(v);\n\n if (Result.isErr(res)) {\n yield* prependPathToValidationErrors(res.value, k);\n }\n }\n }\n },\n );\n\n if (ep === 'reject') {\n const excessKeys = Object.keys(a).filter((key) => !sourceKeys.has(key));\n\n const excessErrors: readonly ValidationError[] = excessKeys.map(\n (key) =>\n ({\n path: [key],\n actualValue: a[key],\n typeName: typeNameFilled,\n expectedType: typeNameFilled,\n details: {\n kind: 'excess-key',\n key,\n },\n }) satisfies ValidationError,\n );\n\n // Combine all errors\n const allErrors = [...defaultErrors, ...excessErrors] as const;\n\n return Arr.isNonEmpty(allErrors)\n ? Result.err(allErrors)\n : // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Result.ok(a as V);\n }\n\n // ep === 'allow'\n return Arr.isNonEmpty(defaultErrors)\n ? Result.err(defaultErrors)\n : // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Result.ok(a as V);\n };\n\n const fill = (a: unknown): V => {\n if (!isRecord(a)) {\n return getDefaultValue();\n }\n\n // fill always produces shape-only values (strips excess)\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Object.fromEntries(\n Object.entries(shape).map(([k, v]) => {\n if (hasKey(a, k)) {\n const value = a[k];\n\n // For optional fields, if the value is undefined, keep it as undefined\n if (value === undefined && v.optional === true) {\n return tp(k, undefined);\n }\n\n return tp(k, v.fill(value));\n }\n\n return tp(k, v.defaultValue);\n }),\n ) as V;\n };\n\n const prune = (a: V): V => {\n // The input is statically guaranteed to be a record.\n const rec: UnknownRecord = a;\n\n // prune keeps only the value paths represented by the shape;\n // unlike fill, it never fills in missing keys with default values\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Obj.filterMap(shape, (v, k) => {\n // Only optional keys can be absent in the input; required keys are\n // statically guaranteed to be present.\n if (v.optional === true) {\n if (!hasKey(rec, k)) {\n return Optional.none;\n }\n\n // For optional fields, if the value is undefined, keep it as undefined\n if (rec[k] === undefined) {\n return Optional.some(undefined);\n }\n }\n\n return Optional.some(v.prune(rec[k]));\n }) as V;\n };\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return {\n typeName: typeNameFilled,\n get defaultValue() {\n return getDefaultValue();\n },\n fill,\n prune,\n validate,\n is: createIsFn(validate),\n assertIs: createAssertFn(validate),\n cast: createCastFn(validate),\n shapeStructure: { kind: 'simple', shape } as const,\n excessProperty: ep,\n } satisfies Type<V> & RecordTypeInternals as Type<V>;\n};\n\n/**\n * Creates a strict record type that rejects excess properties.\n * This is an alias for `record(shape, { excessProperty: 'reject' })`.\n */\nexport const strictRecord = <const S extends UnknownShape>(\n shape: S,\n options?: Partial<Readonly<{ typeName: string }>>,\n): Type<RecordTypeFromShape<S>> =>\n record(shape, {\n typeName: options?.typeName,\n excessProperty: 'reject',\n });\n\n// ---------------------------------------------------------------------------\n// RecordTypeValue (internal — computes value type from shape)\n// ---------------------------------------------------------------------------\n\n/** @internal */\ntype RecordTypeFromShape<S extends UnknownShape> =\n TsFortressInternal.RecordTypeFromShapeImpl<S>;\n\nnamespace TsFortressInternal {\n export type RecordTypeFromShapeImpl<S extends UnknownShape> =\n RecordTypeFromShapeImplSub<S, OptionalTypeKeys<S>>;\n\n type RecordTypeFromShapeImplSub<\n S extends UnknownShape,\n OptionalKeys extends keyof S,\n > =\n TypeEq<OptionalKeys, never> extends true\n ? Readonly<{\n [key in StrictExclude<keyof S, OptionalKeys>]: TypeOf<S[key]>;\n }>\n : TypeEq<keyof S, OptionalKeys> extends true\n ? MergeIntersection<\n Readonly<{ [key in OptionalKeys]?: TypeOf<S[key]> }>\n >\n : MergeIntersection<\n Readonly<\n { [key in OptionalKeys]?: TypeOf<S[key]> } & {\n [key in StrictExclude<keyof S, OptionalKeys>]: TypeOf<S[key]>;\n }\n >\n >;\n\n type OptionalTypeKeys<S extends UnknownShape> = {\n [K in keyof S]: S[K] extends Readonly<{ optional: true }> ? K : never;\n }[keyof S];\n}\n\n// --- expectType assertions ---\n\nexpectType<\n RecordTypeFromShape<Readonly<{ a: Type<0>; b: Type<1>; c: Type<2> }>>,\n Readonly<{ a: 0; b: 1; c: 2 }>\n>('=');\n\nexpectType<\n Type<RecordTypeFromShape<Readonly<{ a: Type<0> }>>>,\n Type<Readonly<{ a: 0 }>>\n>('=');\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"required.d.mts","sourceRoot":"","sources":["../../src/record/required.mts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,IAAI,EAGV,MAAM,aAAa,CAAC;AAKrB;;;GAGG;AACH,eAAO,MAAM,QAAQ,GACnB,KAAK,CAAC,CAAC,SAAS,aAAa,EAC7B,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,cAElD,IAAI,CAAC,CAAC,CAAC,YACT,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC,CACH,KACA,YAAY,CAAC,CAAC,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"required.d.mts","sourceRoot":"","sources":["../../src/record/required.mts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,IAAI,EAGV,MAAM,aAAa,CAAC;AAKrB;;;GAGG;AACH,eAAO,MAAM,QAAQ,GACnB,KAAK,CAAC,CAAC,SAAS,aAAa,EAC7B,KAAK,CAAC,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,cAElD,IAAI,CAAC,CAAC,CAAC,YACT,OAAO,CACf,QAAQ,CAAC;IACP,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC,CACH,KACA,YAAY,CAAC,CAAC,EAAE,gBAAgB,CAkClC,CAAC;AAEF,KAAK,YAAY,CACf,CAAC,SAAS,aAAa,EACvB,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,IACtD,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE7C,uCAAuC;AACvC,KAAK,aAAa,CAChB,CAAC,SAAS,aAAa,EACvB,gBAAgB,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,IAEpE,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,SAAS,IAAI,GAC5C,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GACrB,iBAAiB,CAAC,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC"}
|
package/dist/record/required.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 'ts-data-forge';
|
|
1
|
+
import { Obj } from 'ts-data-forge';
|
|
2
2
|
import { hasRecordInternals, flattenShapeStructure } from '../type.mjs';
|
|
3
3
|
import '@sindresorhus/is';
|
|
4
4
|
import { toUnionKeyString } from '../utils/to-union-string.mjs';
|
|
@@ -21,10 +21,9 @@ const required = (recordType, options) => {
|
|
|
21
21
|
const keysToBeRequired = new Set(
|
|
22
22
|
options?.keysToBeRequired ?? Object.keys(shape)
|
|
23
23
|
);
|
|
24
|
-
const requiredShape =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
24
|
+
const requiredShape = Obj.map(
|
|
25
|
+
shape,
|
|
26
|
+
(v, k) => keysToBeRequired.has(k) ? makeRequired(v) : v
|
|
28
27
|
);
|
|
29
28
|
return record(requiredShape, {
|
|
30
29
|
typeName: typeNameFilled,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"required.mjs","sources":["../../src/record/required.mts"],"sourcesContent":["import { expectType } from 'ts-data-forge';\nimport {\n type ArrayElement,\n type NonEmptyTuple,\n type PartiallyRequired,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n flattenShapeStructure,\n hasRecordInternals,\n type AnyType,\n type ExcessPropertyOption,\n type Type,\n type TypeOf,\n type UnknownShape,\n} from '../type.mjs';\nimport { toUnionKeyString } from '../utils/index.mjs';\nimport { isOptionalProperty, type RequiredPropertyType } from './optional.mjs';\nimport { record } from './record.mjs';\n\n/**\n * Creates a Required type. If keysToBeRequired is set, only those keys are\n * made required, otherwise, all properties are made required.\n */\nexport const required = <\n const R extends UnknownRecord,\n const KeysToBeRequired extends NonEmptyTuple<keyof R & string>,\n>(\n recordType: Type<R>,\n options?: Partial<\n Readonly<{\n keysToBeRequired: KeysToBeRequired;\n typeName: string;\n excessProperty: ExcessPropertyOption;\n }>\n >,\n): RequiredType<R, KeysToBeRequired> => {\n if (!hasRecordInternals(recordType)) {\n throw new Error(\n `Expected a record type but received: ${recordType.typeName}`,\n );\n }\n\n const shape = flattenShapeStructure(recordType.shapeStructure);\n\n if (shape === undefined) {\n throw new Error(\n `required() requires a simple or intersection record type, but received a union type`,\n );\n }\n\n const typeNameFilled: string =\n options?.typeName ??\n (options?.keysToBeRequired === undefined\n ? `Required<${recordType.typeName}>`\n : `PartiallyRequired<${recordType.typeName}, ${toUnionKeyString(options.keysToBeRequired)}>`);\n\n const keysToBeRequired: ReadonlySet<string> = new Set(\n options?.keysToBeRequired ?? Object.keys(shape),\n );\n\n const requiredShape =
|
|
1
|
+
{"version":3,"file":"required.mjs","sources":["../../src/record/required.mts"],"sourcesContent":["import { Obj, expectType } from 'ts-data-forge';\nimport {\n type ArrayElement,\n type NonEmptyTuple,\n type PartiallyRequired,\n type TypeEq,\n type UnknownRecord,\n} from 'ts-type-forge';\nimport {\n flattenShapeStructure,\n hasRecordInternals,\n type AnyType,\n type ExcessPropertyOption,\n type Type,\n type TypeOf,\n type UnknownShape,\n} from '../type.mjs';\nimport { toUnionKeyString } from '../utils/index.mjs';\nimport { isOptionalProperty, type RequiredPropertyType } from './optional.mjs';\nimport { record } from './record.mjs';\n\n/**\n * Creates a Required type. If keysToBeRequired is set, only those keys are\n * made required, otherwise, all properties are made required.\n */\nexport const required = <\n const R extends UnknownRecord,\n const KeysToBeRequired extends NonEmptyTuple<keyof R & string>,\n>(\n recordType: Type<R>,\n options?: Partial<\n Readonly<{\n keysToBeRequired: KeysToBeRequired;\n typeName: string;\n excessProperty: ExcessPropertyOption;\n }>\n >,\n): RequiredType<R, KeysToBeRequired> => {\n if (!hasRecordInternals(recordType)) {\n throw new Error(\n `Expected a record type but received: ${recordType.typeName}`,\n );\n }\n\n const shape = flattenShapeStructure(recordType.shapeStructure);\n\n if (shape === undefined) {\n throw new Error(\n `required() requires a simple or intersection record type, but received a union type`,\n );\n }\n\n const typeNameFilled: string =\n options?.typeName ??\n (options?.keysToBeRequired === undefined\n ? `Required<${recordType.typeName}>`\n : `PartiallyRequired<${recordType.typeName}, ${toUnionKeyString(options.keysToBeRequired)}>`);\n\n const keysToBeRequired: ReadonlySet<string> = new Set(\n options?.keysToBeRequired ?? Object.keys(shape),\n );\n\n const requiredShape = Obj.map(shape, (v, k) =>\n keysToBeRequired.has(k) ? makeRequired(v) : v,\n ) satisfies UnknownShape;\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return record(requiredShape, {\n typeName: typeNameFilled,\n excessProperty: options?.excessProperty ?? recordType.excessProperty,\n }) as unknown as Type<RequiredValue<R, KeysToBeRequired>>;\n};\n\ntype RequiredType<\n R extends UnknownRecord,\n KeysToBeRequired extends NonEmptyTuple<keyof R & string>,\n> = Type<RequiredValue<R, KeysToBeRequired>>;\n\n/** Compute the required value type. */\ntype RequiredValue<\n R extends UnknownRecord,\n KeysToBeRequired extends NonEmptyTuple<keyof R & string> | undefined,\n> =\n TypeEq<KeysToBeRequired, undefined> extends true\n ? Readonly<Required<R>>\n : PartiallyRequired<R, ArrayElement<KeysToBeRequired>>;\n\n/**\n * Makes an optional property required by removing the optional flag.\n */\nconst makeRequired = <T extends AnyType>(t: T): RequiredPropertyType<T> => {\n if (!isOptionalProperty(t)) {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return t as RequiredPropertyType<T>;\n }\n\n const { optional: _, ...rest } = t;\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return rest as RequiredPropertyType<T>;\n};\n\n// --- expectType assertions ---\n\n{\n type Base = ReturnType<\n typeof record<\n Readonly<{ a: Type<0>; b: Type<1 | undefined>; c: Type<2 | undefined> }>\n >\n >;\n\n // required with no keys makes all properties required\n expectType<\n TypeOf<ReturnType<typeof required<TypeOf<Base>, readonly ['a', 'b', 'c']>>>,\n Readonly<Required<Readonly<{ a: 0; b: 1 | undefined; c: 2 | undefined }>>>\n >('=');\n}\n"],"names":[],"mappings":";;;;;;;MAyBa,QAAA,GAAW,CAItB,UAAA,EACA,OAAA,KAOsC;AACtC,EAAA,IAAI,CAAC,kBAAA,CAAmB,UAAU,CAAA,EAAG;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qCAAA,EAAwC,WAAW,QAAQ,CAAA;AAAA,KAC7D;AAAA,EAAA;AAGF,EAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,UAAA,CAAW,cAAc,CAAA;AAE7D,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,mFAAA;AAAA,KACF;AAAA,EAAA;AAGF,EAAA,MAAM,iBACJ,OAAA,EAAS,QAAA,KACR,OAAA,EAAS,gBAAA,KAAqB,SAC3B,CAAA,SAAA,EAAY,UAAA,CAAW,QAAQ,CAAA,CAAA,CAAA,GAC/B,qBAAqB,UAAA,CAAW,QAAQ,KAAK,gBAAA,CAAiB,OAAA,CAAQ,gBAAgB,CAAC,CAAA,CAAA,CAAA,CAAA;AAE7F,EAAA,MAAM,mBAAwC,IAAI,GAAA;AAAA,IAChD,OAAA,EAAS,gBAAA,IAAoB,MAAA,CAAO,IAAA,CAAK,KAAK;AAAA,GAChD;AAEA,EAAA,MAAM,gBAAgB,GAAA,CAAI,GAAA;AAAA,IAAI,KAAA;AAAA,IAAO,CAAC,GAAG,CAAA,KACvC,gBAAA,CAAiB,IAAI,CAAC,CAAA,GAAI,YAAA,CAAa,CAAC,CAAA,GAAI;AAAA,GAC9C;AAGA,EAAA,OAAO,OAAO,aAAA,EAAe;AAAA,IAC3B,QAAA,EAAU,cAAA;AAAA,IACV,cAAA,EAAgB,OAAA,EAAS,cAAA,IAAkB,UAAA,CAAW;AAAA,GACvD,CAAA;AACH;AAmBA,MAAM,YAAA,GAAe,CAAoB,CAAA,KAAkC;AACzE,EAAA,IAAI,CAAC,kBAAA,CAAmB,CAAC,CAAA,EAAG;AAE1B,IAAA,OAAO,CAAA;AAAA,EAAA;AAGT,EAAA,MAAM,EAAE,QAAA,EAAU,CAAA,EAAG,GAAG,MAAK,GAAI,CAAA;AAGjC,EAAA,OAAO,IAAA;AACT,CAAA;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-fortress",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -36,12 +36,15 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@sindresorhus/is": "8.1.0",
|
|
39
|
-
"ts-data-forge": "~14.
|
|
40
|
-
"ts-type-forge": "~9.2.
|
|
39
|
+
"ts-data-forge": "~14.5.0",
|
|
40
|
+
"ts-type-forge": "~9.2.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@vitest/browser-playwright": "4.1.
|
|
44
|
-
"@vitest/ui": "4.1.
|
|
43
|
+
"@vitest/browser-playwright": "4.1.11",
|
|
44
|
+
"@vitest/ui": "4.1.11",
|
|
45
|
+
"eslint-config-typed": "5.10.0",
|
|
46
|
+
"eslint-plugin-ts-data-forge": "0.5.1",
|
|
47
|
+
"eslint-plugin-ts-type-forge": "0.7.1",
|
|
45
48
|
"fp-ts": "2.16.11",
|
|
46
49
|
"io-ts": "2.2.22",
|
|
47
50
|
"playwright": "1.62.1",
|
|
@@ -49,14 +52,11 @@
|
|
|
49
52
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
50
53
|
"prettier-plugin-packagejson": "3.0.2",
|
|
51
54
|
"rollup": "4.62.4",
|
|
55
|
+
"ts-repo-utils": "10.3.2",
|
|
52
56
|
"typedoc": "0.28.20",
|
|
53
57
|
"typedoc-github-theme": "0.4.0",
|
|
54
58
|
"vite": "8.2.1",
|
|
55
|
-
"zod": "4.4.3"
|
|
56
|
-
"eslint-config-typed": "5.9.3",
|
|
57
|
-
"eslint-plugin-ts-data-forge": "0.4.8",
|
|
58
|
-
"eslint-plugin-ts-type-forge": "0.6.6",
|
|
59
|
-
"ts-repo-utils": "10.2.0"
|
|
59
|
+
"zod": "4.4.3"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=22.22.2",
|
|
@@ -201,27 +201,27 @@ const createConstraintsPredicate =
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
if (gt !== undefined && !(value > gt)) {
|
|
204
|
-
return Result.err({ constraint: 'gt', value:
|
|
204
|
+
return Result.err({ constraint: 'gt', value: gt.toString() } as const);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
if (gte !== undefined && !(value >= gte)) {
|
|
208
|
-
return Result.err({ constraint: 'gte', value:
|
|
208
|
+
return Result.err({ constraint: 'gte', value: gte.toString() } as const);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
if (min !== undefined && !(value >= min)) {
|
|
212
|
-
return Result.err({ constraint: 'min', value:
|
|
212
|
+
return Result.err({ constraint: 'min', value: min.toString() } as const);
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
if (lt !== undefined && !(value < lt)) {
|
|
216
|
-
return Result.err({ constraint: 'lt', value:
|
|
216
|
+
return Result.err({ constraint: 'lt', value: lt.toString() } as const);
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
if (lte !== undefined && !(value <= lte)) {
|
|
220
|
-
return Result.err({ constraint: 'lte', value:
|
|
220
|
+
return Result.err({ constraint: 'lte', value: lte.toString() } as const);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
if (max !== undefined && !(value <= max)) {
|
|
224
|
-
return Result.err({ constraint: 'max', value:
|
|
224
|
+
return Result.err({ constraint: 'max', value: max.toString() } as const);
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// `value % 0n` throws a RangeError, so the zero divisor is handled
|
|
@@ -231,13 +231,13 @@ const createConstraintsPredicate =
|
|
|
231
231
|
if (value !== 0n) {
|
|
232
232
|
return Result.err({
|
|
233
233
|
constraint: 'multipleOf',
|
|
234
|
-
value:
|
|
234
|
+
value: multipleOf.toString(),
|
|
235
235
|
} as const);
|
|
236
236
|
}
|
|
237
237
|
} else if (value % multipleOf !== 0n) {
|
|
238
238
|
return Result.err({
|
|
239
239
|
constraint: 'multipleOf',
|
|
240
|
-
value:
|
|
240
|
+
value: multipleOf.toString(),
|
|
241
241
|
} as const);
|
|
242
242
|
}
|
|
243
243
|
}
|
|
@@ -247,11 +247,14 @@ const createConstraintsPredicate =
|
|
|
247
247
|
if (value !== 0n) {
|
|
248
248
|
return Result.err({
|
|
249
249
|
constraint: 'step',
|
|
250
|
-
value:
|
|
250
|
+
value: step.toString(),
|
|
251
251
|
} as const);
|
|
252
252
|
}
|
|
253
253
|
} else if (value % step !== 0n) {
|
|
254
|
-
return Result.err({
|
|
254
|
+
return Result.err({
|
|
255
|
+
constraint: 'step',
|
|
256
|
+
value: step.toString(),
|
|
257
|
+
} as const);
|
|
255
258
|
}
|
|
256
259
|
}
|
|
257
260
|
|
|
@@ -373,27 +373,27 @@ const createConstraintsPredicate =
|
|
|
373
373
|
}
|
|
374
374
|
|
|
375
375
|
if (gt !== undefined && !(value > gt)) {
|
|
376
|
-
return Result.err({ constraint: 'gt', value:
|
|
376
|
+
return Result.err({ constraint: 'gt', value: gt.toString() } as const);
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
if (gte !== undefined && !(value >= gte)) {
|
|
380
|
-
return Result.err({ constraint: 'gte', value:
|
|
380
|
+
return Result.err({ constraint: 'gte', value: gte.toString() } as const);
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
if (min !== undefined && !(value >= min)) {
|
|
384
|
-
return Result.err({ constraint: 'min', value:
|
|
384
|
+
return Result.err({ constraint: 'min', value: min.toString() } as const);
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
if (lt !== undefined && !(value < lt)) {
|
|
388
|
-
return Result.err({ constraint: 'lt', value:
|
|
388
|
+
return Result.err({ constraint: 'lt', value: lt.toString() } as const);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
if (lte !== undefined && !(value <= lte)) {
|
|
392
|
-
return Result.err({ constraint: 'lte', value:
|
|
392
|
+
return Result.err({ constraint: 'lte', value: lte.toString() } as const);
|
|
393
393
|
}
|
|
394
394
|
|
|
395
395
|
if (max !== undefined && !(value <= max)) {
|
|
396
|
-
return Result.err({ constraint: 'max', value:
|
|
396
|
+
return Result.err({ constraint: 'max', value: max.toString() } as const);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
// `value % 0` throws a RangeError, so the zero divisor is handled
|
|
@@ -403,13 +403,13 @@ const createConstraintsPredicate =
|
|
|
403
403
|
if (value !== 0) {
|
|
404
404
|
return Result.err({
|
|
405
405
|
constraint: 'multipleOf',
|
|
406
|
-
value:
|
|
406
|
+
value: multipleOf.toString(),
|
|
407
407
|
} as const);
|
|
408
408
|
}
|
|
409
409
|
} else if (value % multipleOf !== 0) {
|
|
410
410
|
return Result.err({
|
|
411
411
|
constraint: 'multipleOf',
|
|
412
|
-
value:
|
|
412
|
+
value: multipleOf.toString(),
|
|
413
413
|
} as const);
|
|
414
414
|
}
|
|
415
415
|
}
|
|
@@ -419,11 +419,14 @@ const createConstraintsPredicate =
|
|
|
419
419
|
if (value !== 0) {
|
|
420
420
|
return Result.err({
|
|
421
421
|
constraint: 'step',
|
|
422
|
-
value:
|
|
422
|
+
value: step.toString(),
|
|
423
423
|
} as const);
|
|
424
424
|
}
|
|
425
425
|
} else if (value % step !== 0) {
|
|
426
|
-
return Result.err({
|
|
426
|
+
return Result.err({
|
|
427
|
+
constraint: 'step',
|
|
428
|
+
value: step.toString(),
|
|
429
|
+
} as const);
|
|
427
430
|
}
|
|
428
431
|
}
|
|
429
432
|
|
package/src/record/partial.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectType } from 'ts-data-forge';
|
|
1
|
+
import { Obj, expectType } from 'ts-data-forge';
|
|
2
2
|
import {
|
|
3
3
|
type ArrayElement,
|
|
4
4
|
type NonEmptyTuple,
|
|
@@ -59,10 +59,8 @@ export const partial = <
|
|
|
59
59
|
options?.keysToBeOptional ?? Object.keys(shape),
|
|
60
60
|
);
|
|
61
61
|
|
|
62
|
-
const partialShape =
|
|
63
|
-
|
|
64
|
-
([k, v]) => [k, keysToBeOptional.has(k) ? optional(v) : v] as const,
|
|
65
|
-
),
|
|
62
|
+
const partialShape = Obj.map(shape, (v, k) =>
|
|
63
|
+
keysToBeOptional.has(k) ? optional(v) : v,
|
|
66
64
|
) satisfies UnknownShape;
|
|
67
65
|
|
|
68
66
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
package/src/record/record.mts
CHANGED
|
@@ -52,7 +52,11 @@ export const record = <
|
|
|
52
52
|
): Type<RecordTypeFromShape<S>> => {
|
|
53
53
|
type V = RecordTypeFromShape<S>;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
// Annotated rather than inferred: the strict standard library types
|
|
56
|
+
// `Object.keys` as the record's own key union, which would make `has` reject
|
|
57
|
+
// the plain `string` keys read back off the value being validated. The
|
|
58
|
+
// membership test is the point here, so the wider element type is correct.
|
|
59
|
+
const sourceKeys: ReadonlySet<string> = new Set(Object.keys(shape));
|
|
56
60
|
|
|
57
61
|
const typeNameFilled: string =
|
|
58
62
|
options?.typeName ??
|
package/src/record/required.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectType } from 'ts-data-forge';
|
|
1
|
+
import { Obj, expectType } from 'ts-data-forge';
|
|
2
2
|
import {
|
|
3
3
|
type ArrayElement,
|
|
4
4
|
type NonEmptyTuple,
|
|
@@ -60,10 +60,8 @@ export const required = <
|
|
|
60
60
|
options?.keysToBeRequired ?? Object.keys(shape),
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
const requiredShape =
|
|
64
|
-
|
|
65
|
-
([k, v]) => [k, keysToBeRequired.has(k) ? makeRequired(v) : v] as const,
|
|
66
|
-
),
|
|
63
|
+
const requiredShape = Obj.map(shape, (v, k) =>
|
|
64
|
+
keysToBeRequired.has(k) ? makeRequired(v) : v,
|
|
67
65
|
) satisfies UnknownShape;
|
|
68
66
|
|
|
69
67
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|