is-kit 1.4.2 → 1.6.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 +43 -4
- package/dist/index.d.mts +64 -6
- package/dist/index.d.ts +64 -6
- package/dist/index.js +61 -3
- package/dist/index.mjs +58 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,9 +69,11 @@ import {
|
|
|
69
69
|
and,
|
|
70
70
|
or,
|
|
71
71
|
not,
|
|
72
|
+
mapOf,
|
|
73
|
+
optionalKey,
|
|
74
|
+
setOf,
|
|
72
75
|
struct,
|
|
73
76
|
oneOfValues,
|
|
74
|
-
optional,
|
|
75
77
|
isNumber,
|
|
76
78
|
isString,
|
|
77
79
|
predicateToRefine
|
|
@@ -90,11 +92,13 @@ const isOther = not(isShortOrPositive);
|
|
|
90
92
|
|
|
91
93
|
// Define object shapes
|
|
92
94
|
const isRole = oneOfValues(['admin', 'member'] as const);
|
|
95
|
+
const isTags = setOf(isString);
|
|
96
|
+
const isScores = mapOf(isString, isNumber);
|
|
93
97
|
const isUser = struct({
|
|
94
98
|
id: isPositive, // number > 0
|
|
95
99
|
name: isString, // string
|
|
96
100
|
role: isRole, // 'admin' | 'member'
|
|
97
|
-
nickname:
|
|
101
|
+
nickname: optionalKey(isShortString) // key may be absent; when present, string <= 3
|
|
98
102
|
});
|
|
99
103
|
|
|
100
104
|
// Use them
|
|
@@ -102,6 +106,8 @@ isPositive(3); // true
|
|
|
102
106
|
isShortOrPositive('foo'); // true
|
|
103
107
|
isShortOrPositive(false); // false
|
|
104
108
|
isOther('x'); // true
|
|
109
|
+
isTags(new Set(['new', 'vip'])); // true
|
|
110
|
+
isScores(new Map([['math', 98]])); // true
|
|
105
111
|
|
|
106
112
|
const maybeUser: unknown = { id: 7, name: 'Rin', role: 'admin' };
|
|
107
113
|
if (isUser(maybeUser)) {
|
|
@@ -111,10 +117,41 @@ if (isUser(maybeUser)) {
|
|
|
111
117
|
}
|
|
112
118
|
```
|
|
113
119
|
|
|
120
|
+
Use `optionalKey(...)` for key-level optional properties in `struct`.
|
|
121
|
+
Use `optional(...)` when the key exists but the value itself may be `undefined`.
|
|
122
|
+
Combine them as `optionalKey(optional(guard))` when both are allowed.
|
|
123
|
+
|
|
114
124
|
Composed guards stay reusable:
|
|
115
125
|
`isPositive` can be used standalone or as part of a `struct` definition.
|
|
116
126
|
|
|
117
|
-
When validating complex shapes, reach for `struct`
|
|
127
|
+
When validating complex shapes, reach for `struct` and collection
|
|
128
|
+
combinators like `arrayOf`, `setOf`, `mapOf`, `recordOf`, or `oneOf`.
|
|
129
|
+
|
|
130
|
+
### Collection combinators
|
|
131
|
+
|
|
132
|
+
Use `arrayOf`, `setOf`, `mapOf`, and `recordOf` to validate homogeneous
|
|
133
|
+
collections while preserving precise readonly types.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import {
|
|
137
|
+
arrayOf,
|
|
138
|
+
mapOf,
|
|
139
|
+
recordOf,
|
|
140
|
+
setOf,
|
|
141
|
+
isNumber,
|
|
142
|
+
isString
|
|
143
|
+
} from 'is-kit';
|
|
144
|
+
|
|
145
|
+
const isStringArray = arrayOf(isString);
|
|
146
|
+
const isStringSet = setOf(isString);
|
|
147
|
+
const isScoreMap = mapOf(isString, isNumber);
|
|
148
|
+
const isStringRecord = recordOf(isString, isString);
|
|
149
|
+
|
|
150
|
+
isStringArray(['a', 'b']); // true
|
|
151
|
+
isStringSet(new Set(['a', 'b'])); // true
|
|
152
|
+
isScoreMap(new Map([['math', 98]])); // true
|
|
153
|
+
isStringRecord({ a: 'x', b: 'y' }); // true
|
|
154
|
+
```
|
|
118
155
|
|
|
119
156
|
### Primitive guards
|
|
120
157
|
|
|
@@ -161,6 +198,8 @@ isInfiniteNumber(1); // false
|
|
|
161
198
|
|
|
162
199
|
Object/built-in guards cover arrays, dates, maps/sets, and more. Use
|
|
163
200
|
`isInstanceOf` when you want a reusable guard from a class constructor.
|
|
201
|
+
For content-aware map/set validation, pair `isMap` / `isSet` with `mapOf`
|
|
202
|
+
and `setOf`.
|
|
164
203
|
|
|
165
204
|
```ts
|
|
166
205
|
import { isArray, isDate, isInstanceOf } from 'is-kit';
|
|
@@ -180,7 +219,7 @@ isAnimal({}); // false
|
|
|
180
219
|
|
|
181
220
|
- **Define once**: `define<T>(fn)` turns a plain function into a type guard.
|
|
182
221
|
- **Upgrade predicates**: `predicateToRefine(fn)` adds narrowing.
|
|
183
|
-
- **Compose freely**: `and`, `or`, `not`, `oneOf`, `arrayOf`, `struct` …
|
|
222
|
+
- **Compose freely**: `and`, `or`, `not`, `oneOf`, `arrayOf`, `setOf`, `mapOf`, `struct` …
|
|
184
223
|
- **Stay ergonomic**: helpers like `nullable`, `optional`, `equals`, `safeParse`, `assert`, `hasKey`, `hasKeys`, `narrowKeyTo`.
|
|
185
224
|
|
|
186
225
|
### Key Helpers
|
package/dist/index.d.mts
CHANGED
|
@@ -13,13 +13,43 @@ type ParseResult<T> = {
|
|
|
13
13
|
};
|
|
14
14
|
type GuardedOf<F> = F extends (value: unknown) => value is infer G ? G : never;
|
|
15
15
|
type GuardedWithin<Fs, A> = Extract<Fs extends readonly unknown[] ? GuardedOf<Fs[number]> : never, A>;
|
|
16
|
-
type Schema = Readonly<Record<string, Predicate<unknown>>>;
|
|
17
|
-
type InferSchema<S extends Schema> = {
|
|
18
|
-
readonly [K in keyof S]: GuardedOf<S[K]>;
|
|
19
|
-
};
|
|
20
16
|
|
|
21
17
|
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
22
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Marks a `struct` schema field as optional at the key level.
|
|
21
|
+
*/
|
|
22
|
+
type OptionalSchemaField<G extends Predicate<unknown>> = Readonly<{
|
|
23
|
+
optional: true;
|
|
24
|
+
guard: G;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Field accepted by `struct` schemas.
|
|
28
|
+
*/
|
|
29
|
+
type SchemaField = Predicate<unknown> | OptionalSchemaField<Predicate<unknown>>;
|
|
30
|
+
/**
|
|
31
|
+
* Object schema consumed by `struct`.
|
|
32
|
+
*/
|
|
33
|
+
type Schema = Readonly<Record<string, SchemaField>>;
|
|
34
|
+
type Simplify<T> = {
|
|
35
|
+
[K in keyof T]: T[K];
|
|
36
|
+
};
|
|
37
|
+
type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
|
|
38
|
+
type RequiredSchemaKeys<S extends Schema> = {
|
|
39
|
+
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? never : K;
|
|
40
|
+
}[keyof S];
|
|
41
|
+
type OptionalSchemaKeys<S extends Schema> = {
|
|
42
|
+
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? K : never;
|
|
43
|
+
}[keyof S];
|
|
44
|
+
/**
|
|
45
|
+
* Infers the readonly object type produced by a `struct` schema.
|
|
46
|
+
*/
|
|
47
|
+
type InferSchema<S extends Schema> = Simplify<{
|
|
48
|
+
readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
|
|
49
|
+
} & {
|
|
50
|
+
readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
23
53
|
/**
|
|
24
54
|
* Wraps a user function as a typed predicate.
|
|
25
55
|
*
|
|
@@ -295,6 +325,23 @@ declare const isPrimitive: Guard<string | number | bigint | boolean | symbol | n
|
|
|
295
325
|
*/
|
|
296
326
|
declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
|
|
297
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Validates a set where every value satisfies the provided guard.
|
|
330
|
+
*
|
|
331
|
+
* @param valueGuard Guard applied to each set value.
|
|
332
|
+
* @returns Predicate narrowing to a readonly set of the guarded value type.
|
|
333
|
+
*/
|
|
334
|
+
declare function setOf<VF extends Predicate<unknown>>(valueGuard: VF): Predicate<ReadonlySet<GuardedOf<VF>>>;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Validates a map where every key and value satisfies the provided guards.
|
|
338
|
+
*
|
|
339
|
+
* @param keyGuard Guard applied to each map key.
|
|
340
|
+
* @param valueGuard Guard applied to each map value.
|
|
341
|
+
* @returns Predicate narrowing to a readonly map with guarded key/value types.
|
|
342
|
+
*/
|
|
343
|
+
declare function mapOf<KF extends Predicate<unknown>, VF extends Predicate<unknown>>(keyGuard: KF, valueGuard: VF): Predicate<ReadonlyMap<GuardedOf<KF>, GuardedOf<VF>>>;
|
|
344
|
+
|
|
298
345
|
/**
|
|
299
346
|
* Validates a fixed-length tuple by applying element-wise guards.
|
|
300
347
|
*
|
|
@@ -323,9 +370,20 @@ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (i
|
|
|
323
370
|
*/
|
|
324
371
|
declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
|
|
325
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Marks a struct schema field as optional at the key level.
|
|
375
|
+
*
|
|
376
|
+
* When used inside `struct`, the property may be absent. If the property exists,
|
|
377
|
+
* its value must satisfy the wrapped guard.
|
|
378
|
+
*
|
|
379
|
+
* @param guard Guard used to validate the property value when the key exists.
|
|
380
|
+
* @returns Schema field marker understood by `struct`.
|
|
381
|
+
*/
|
|
382
|
+
declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSchemaField<G>;
|
|
326
383
|
/**
|
|
327
384
|
* Validates an object against a field-to-guard schema.
|
|
328
|
-
* Keys in the schema are required
|
|
385
|
+
* Keys in the schema are required unless wrapped with `optionalKey`; optionally
|
|
386
|
+
* rejects extra keys when `exact: true`.
|
|
329
387
|
*
|
|
330
388
|
* @param schema Record of property guards.
|
|
331
389
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
@@ -505,4 +563,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
|
|
|
505
563
|
*/
|
|
506
564
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
507
565
|
|
|
508
|
-
export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
|
|
566
|
+
export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, mapOf, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,13 +13,43 @@ type ParseResult<T> = {
|
|
|
13
13
|
};
|
|
14
14
|
type GuardedOf<F> = F extends (value: unknown) => value is infer G ? G : never;
|
|
15
15
|
type GuardedWithin<Fs, A> = Extract<Fs extends readonly unknown[] ? GuardedOf<Fs[number]> : never, A>;
|
|
16
|
-
type Schema = Readonly<Record<string, Predicate<unknown>>>;
|
|
17
|
-
type InferSchema<S extends Schema> = {
|
|
18
|
-
readonly [K in keyof S]: GuardedOf<S[K]>;
|
|
19
|
-
};
|
|
20
16
|
|
|
21
17
|
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
22
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Marks a `struct` schema field as optional at the key level.
|
|
21
|
+
*/
|
|
22
|
+
type OptionalSchemaField<G extends Predicate<unknown>> = Readonly<{
|
|
23
|
+
optional: true;
|
|
24
|
+
guard: G;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Field accepted by `struct` schemas.
|
|
28
|
+
*/
|
|
29
|
+
type SchemaField = Predicate<unknown> | OptionalSchemaField<Predicate<unknown>>;
|
|
30
|
+
/**
|
|
31
|
+
* Object schema consumed by `struct`.
|
|
32
|
+
*/
|
|
33
|
+
type Schema = Readonly<Record<string, SchemaField>>;
|
|
34
|
+
type Simplify<T> = {
|
|
35
|
+
[K in keyof T]: T[K];
|
|
36
|
+
};
|
|
37
|
+
type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
|
|
38
|
+
type RequiredSchemaKeys<S extends Schema> = {
|
|
39
|
+
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? never : K;
|
|
40
|
+
}[keyof S];
|
|
41
|
+
type OptionalSchemaKeys<S extends Schema> = {
|
|
42
|
+
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? K : never;
|
|
43
|
+
}[keyof S];
|
|
44
|
+
/**
|
|
45
|
+
* Infers the readonly object type produced by a `struct` schema.
|
|
46
|
+
*/
|
|
47
|
+
type InferSchema<S extends Schema> = Simplify<{
|
|
48
|
+
readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
|
|
49
|
+
} & {
|
|
50
|
+
readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
23
53
|
/**
|
|
24
54
|
* Wraps a user function as a typed predicate.
|
|
25
55
|
*
|
|
@@ -295,6 +325,23 @@ declare const isPrimitive: Guard<string | number | bigint | boolean | symbol | n
|
|
|
295
325
|
*/
|
|
296
326
|
declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
|
|
297
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Validates a set where every value satisfies the provided guard.
|
|
330
|
+
*
|
|
331
|
+
* @param valueGuard Guard applied to each set value.
|
|
332
|
+
* @returns Predicate narrowing to a readonly set of the guarded value type.
|
|
333
|
+
*/
|
|
334
|
+
declare function setOf<VF extends Predicate<unknown>>(valueGuard: VF): Predicate<ReadonlySet<GuardedOf<VF>>>;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Validates a map where every key and value satisfies the provided guards.
|
|
338
|
+
*
|
|
339
|
+
* @param keyGuard Guard applied to each map key.
|
|
340
|
+
* @param valueGuard Guard applied to each map value.
|
|
341
|
+
* @returns Predicate narrowing to a readonly map with guarded key/value types.
|
|
342
|
+
*/
|
|
343
|
+
declare function mapOf<KF extends Predicate<unknown>, VF extends Predicate<unknown>>(keyGuard: KF, valueGuard: VF): Predicate<ReadonlyMap<GuardedOf<KF>, GuardedOf<VF>>>;
|
|
344
|
+
|
|
298
345
|
/**
|
|
299
346
|
* Validates a fixed-length tuple by applying element-wise guards.
|
|
300
347
|
*
|
|
@@ -323,9 +370,20 @@ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (i
|
|
|
323
370
|
*/
|
|
324
371
|
declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
|
|
325
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Marks a struct schema field as optional at the key level.
|
|
375
|
+
*
|
|
376
|
+
* When used inside `struct`, the property may be absent. If the property exists,
|
|
377
|
+
* its value must satisfy the wrapped guard.
|
|
378
|
+
*
|
|
379
|
+
* @param guard Guard used to validate the property value when the key exists.
|
|
380
|
+
* @returns Schema field marker understood by `struct`.
|
|
381
|
+
*/
|
|
382
|
+
declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSchemaField<G>;
|
|
326
383
|
/**
|
|
327
384
|
* Validates an object against a field-to-guard schema.
|
|
328
|
-
* Keys in the schema are required
|
|
385
|
+
* Keys in the schema are required unless wrapped with `optionalKey`; optionally
|
|
386
|
+
* rejects extra keys when `exact: true`.
|
|
329
387
|
*
|
|
330
388
|
* @param schema Record of property guards.
|
|
331
389
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
@@ -505,4 +563,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
|
|
|
505
563
|
*/
|
|
506
564
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
507
565
|
|
|
508
|
-
export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
|
|
566
|
+
export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, mapOf, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
|
package/dist/index.js
CHANGED
|
@@ -68,6 +68,7 @@ __export(index_exports, {
|
|
|
68
68
|
isWeakMap: () => isWeakMap,
|
|
69
69
|
isWeakSet: () => isWeakSet,
|
|
70
70
|
isZero: () => isZero,
|
|
71
|
+
mapOf: () => mapOf,
|
|
71
72
|
narrowKeyTo: () => narrowKeyTo,
|
|
72
73
|
nonNull: () => nonNull,
|
|
73
74
|
not: () => not,
|
|
@@ -76,12 +77,14 @@ __export(index_exports, {
|
|
|
76
77
|
oneOf: () => oneOf,
|
|
77
78
|
oneOfValues: () => oneOfValues,
|
|
78
79
|
optional: () => optional,
|
|
80
|
+
optionalKey: () => optionalKey,
|
|
79
81
|
or: () => or,
|
|
80
82
|
predicateToRefine: () => predicateToRefine,
|
|
81
83
|
recordOf: () => recordOf,
|
|
82
84
|
required: () => required,
|
|
83
85
|
safeParse: () => safeParse,
|
|
84
86
|
safeParseWith: () => safeParseWith,
|
|
87
|
+
setOf: () => setOf,
|
|
85
88
|
struct: () => struct,
|
|
86
89
|
toBooleanPredicates: () => toBooleanPredicates,
|
|
87
90
|
tupleOf: () => tupleOf
|
|
@@ -302,6 +305,29 @@ function arrayOf(elementGuard) {
|
|
|
302
305
|
};
|
|
303
306
|
}
|
|
304
307
|
|
|
308
|
+
// src/core/combinators/set.ts
|
|
309
|
+
function setOf(valueGuard) {
|
|
310
|
+
return define((input) => {
|
|
311
|
+
if (!isSet(input)) return false;
|
|
312
|
+
for (const value of input.values()) {
|
|
313
|
+
if (!valueGuard(value)) return false;
|
|
314
|
+
}
|
|
315
|
+
return true;
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/core/combinators/map.ts
|
|
320
|
+
function mapOf(keyGuard, valueGuard) {
|
|
321
|
+
return define((input) => {
|
|
322
|
+
if (!isMap(input)) return false;
|
|
323
|
+
for (const [key, value] of input.entries()) {
|
|
324
|
+
if (!keyGuard(key)) return false;
|
|
325
|
+
if (!valueGuard(value)) return false;
|
|
326
|
+
}
|
|
327
|
+
return true;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
305
331
|
// src/core/combinators/tuple.ts
|
|
306
332
|
function tupleOf(...guards) {
|
|
307
333
|
return (input) => {
|
|
@@ -332,15 +358,44 @@ function recordOf(keyFunction, valueFunction) {
|
|
|
332
358
|
}
|
|
333
359
|
|
|
334
360
|
// src/core/combinators/struct.ts
|
|
335
|
-
var
|
|
361
|
+
var hasOwnKey = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
362
|
+
var isOptionalSchemaField = define(
|
|
363
|
+
// WHY: Optional fields are represented as a small tagged object so `struct`
|
|
364
|
+
// can distinguish schema metadata from plain predicate functions up front.
|
|
365
|
+
(field) => isObject(field) && field.optional === true && typeof field.guard === "function"
|
|
366
|
+
);
|
|
367
|
+
var hasRequiredKeys = (obj, entries) => (
|
|
368
|
+
// WHY: Required fields must be own properties; inherited values should not
|
|
369
|
+
// satisfy a schema because `struct` models object payload shape, not prototype chains.
|
|
370
|
+
entries.every(([key, guard]) => hasOwnKey(obj, key) && guard(obj[key]))
|
|
371
|
+
);
|
|
372
|
+
var hasValidOptionalKeys = (obj, entries) => (
|
|
373
|
+
// WHY: Optional keys are validated only when present. Missing keys stay valid
|
|
374
|
+
// without forcing callers to encode `undefined` into the value guard.
|
|
375
|
+
entries.every(([key, guard]) => !hasOwnKey(obj, key) || guard(obj[key]))
|
|
376
|
+
);
|
|
336
377
|
var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
|
|
378
|
+
function optionalKey(guard) {
|
|
379
|
+
return { optional: true, guard };
|
|
380
|
+
}
|
|
337
381
|
function struct(schema, options) {
|
|
338
|
-
const
|
|
382
|
+
const requiredEntries = [];
|
|
383
|
+
const optionalEntries = [];
|
|
384
|
+
const schemaKeys = [];
|
|
385
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
386
|
+
schemaKeys.push(key);
|
|
387
|
+
if (isOptionalSchemaField(field)) {
|
|
388
|
+
optionalEntries.push([key, field.guard]);
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
requiredEntries.push([key, field]);
|
|
392
|
+
}
|
|
339
393
|
const allowed = options?.exact ? new Set(schemaKeys) : null;
|
|
340
394
|
return (input) => {
|
|
341
395
|
if (!isPlainObject(input)) return false;
|
|
342
396
|
const obj = input;
|
|
343
|
-
if (!hasRequiredKeys(obj,
|
|
397
|
+
if (!hasRequiredKeys(obj, requiredEntries)) return false;
|
|
398
|
+
if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
|
|
344
399
|
if (!allowed) return true;
|
|
345
400
|
return hasOnlyAllowedKeys(obj, allowed);
|
|
346
401
|
};
|
|
@@ -455,6 +510,7 @@ function narrowKeyTo(guard, key) {
|
|
|
455
510
|
isWeakMap,
|
|
456
511
|
isWeakSet,
|
|
457
512
|
isZero,
|
|
513
|
+
mapOf,
|
|
458
514
|
narrowKeyTo,
|
|
459
515
|
nonNull,
|
|
460
516
|
not,
|
|
@@ -463,12 +519,14 @@ function narrowKeyTo(guard, key) {
|
|
|
463
519
|
oneOf,
|
|
464
520
|
oneOfValues,
|
|
465
521
|
optional,
|
|
522
|
+
optionalKey,
|
|
466
523
|
or,
|
|
467
524
|
predicateToRefine,
|
|
468
525
|
recordOf,
|
|
469
526
|
required,
|
|
470
527
|
safeParse,
|
|
471
528
|
safeParseWith,
|
|
529
|
+
setOf,
|
|
472
530
|
struct,
|
|
473
531
|
toBooleanPredicates,
|
|
474
532
|
tupleOf
|
package/dist/index.mjs
CHANGED
|
@@ -212,6 +212,29 @@ function arrayOf(elementGuard) {
|
|
|
212
212
|
};
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
// src/core/combinators/set.ts
|
|
216
|
+
function setOf(valueGuard) {
|
|
217
|
+
return define((input) => {
|
|
218
|
+
if (!isSet(input)) return false;
|
|
219
|
+
for (const value of input.values()) {
|
|
220
|
+
if (!valueGuard(value)) return false;
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/core/combinators/map.ts
|
|
227
|
+
function mapOf(keyGuard, valueGuard) {
|
|
228
|
+
return define((input) => {
|
|
229
|
+
if (!isMap(input)) return false;
|
|
230
|
+
for (const [key, value] of input.entries()) {
|
|
231
|
+
if (!keyGuard(key)) return false;
|
|
232
|
+
if (!valueGuard(value)) return false;
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
215
238
|
// src/core/combinators/tuple.ts
|
|
216
239
|
function tupleOf(...guards) {
|
|
217
240
|
return (input) => {
|
|
@@ -242,15 +265,44 @@ function recordOf(keyFunction, valueFunction) {
|
|
|
242
265
|
}
|
|
243
266
|
|
|
244
267
|
// src/core/combinators/struct.ts
|
|
245
|
-
var
|
|
268
|
+
var hasOwnKey = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
269
|
+
var isOptionalSchemaField = define(
|
|
270
|
+
// WHY: Optional fields are represented as a small tagged object so `struct`
|
|
271
|
+
// can distinguish schema metadata from plain predicate functions up front.
|
|
272
|
+
(field) => isObject(field) && field.optional === true && typeof field.guard === "function"
|
|
273
|
+
);
|
|
274
|
+
var hasRequiredKeys = (obj, entries) => (
|
|
275
|
+
// WHY: Required fields must be own properties; inherited values should not
|
|
276
|
+
// satisfy a schema because `struct` models object payload shape, not prototype chains.
|
|
277
|
+
entries.every(([key, guard]) => hasOwnKey(obj, key) && guard(obj[key]))
|
|
278
|
+
);
|
|
279
|
+
var hasValidOptionalKeys = (obj, entries) => (
|
|
280
|
+
// WHY: Optional keys are validated only when present. Missing keys stay valid
|
|
281
|
+
// without forcing callers to encode `undefined` into the value guard.
|
|
282
|
+
entries.every(([key, guard]) => !hasOwnKey(obj, key) || guard(obj[key]))
|
|
283
|
+
);
|
|
246
284
|
var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
|
|
285
|
+
function optionalKey(guard) {
|
|
286
|
+
return { optional: true, guard };
|
|
287
|
+
}
|
|
247
288
|
function struct(schema, options) {
|
|
248
|
-
const
|
|
289
|
+
const requiredEntries = [];
|
|
290
|
+
const optionalEntries = [];
|
|
291
|
+
const schemaKeys = [];
|
|
292
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
293
|
+
schemaKeys.push(key);
|
|
294
|
+
if (isOptionalSchemaField(field)) {
|
|
295
|
+
optionalEntries.push([key, field.guard]);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
requiredEntries.push([key, field]);
|
|
299
|
+
}
|
|
249
300
|
const allowed = options?.exact ? new Set(schemaKeys) : null;
|
|
250
301
|
return (input) => {
|
|
251
302
|
if (!isPlainObject(input)) return false;
|
|
252
303
|
const obj = input;
|
|
253
|
-
if (!hasRequiredKeys(obj,
|
|
304
|
+
if (!hasRequiredKeys(obj, requiredEntries)) return false;
|
|
305
|
+
if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
|
|
254
306
|
if (!allowed) return true;
|
|
255
307
|
return hasOnlyAllowedKeys(obj, allowed);
|
|
256
308
|
};
|
|
@@ -364,6 +416,7 @@ export {
|
|
|
364
416
|
isWeakMap,
|
|
365
417
|
isWeakSet,
|
|
366
418
|
isZero,
|
|
419
|
+
mapOf,
|
|
367
420
|
narrowKeyTo,
|
|
368
421
|
nonNull,
|
|
369
422
|
not,
|
|
@@ -372,12 +425,14 @@ export {
|
|
|
372
425
|
oneOf,
|
|
373
426
|
oneOfValues,
|
|
374
427
|
optional,
|
|
428
|
+
optionalKey,
|
|
375
429
|
or,
|
|
376
430
|
predicateToRefine,
|
|
377
431
|
recordOf,
|
|
378
432
|
required,
|
|
379
433
|
safeParse,
|
|
380
434
|
safeParseWith,
|
|
435
|
+
setOf,
|
|
381
436
|
struct,
|
|
382
437
|
toBooleanPredicates,
|
|
383
438
|
tupleOf
|