is-kit 1.4.2 → 1.5.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 +6 -2
- package/dist/index.d.mts +47 -6
- package/dist/index.d.ts +47 -6
- package/dist/index.js +34 -3
- package/dist/index.mjs +33 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,9 +69,9 @@ import {
|
|
|
69
69
|
and,
|
|
70
70
|
or,
|
|
71
71
|
not,
|
|
72
|
+
optionalKey,
|
|
72
73
|
struct,
|
|
73
74
|
oneOfValues,
|
|
74
|
-
optional,
|
|
75
75
|
isNumber,
|
|
76
76
|
isString,
|
|
77
77
|
predicateToRefine
|
|
@@ -94,7 +94,7 @@ const isUser = struct({
|
|
|
94
94
|
id: isPositive, // number > 0
|
|
95
95
|
name: isString, // string
|
|
96
96
|
role: isRole, // 'admin' | 'member'
|
|
97
|
-
nickname:
|
|
97
|
+
nickname: optionalKey(isShortString) // key may be absent; when present, string <= 3
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
// Use them
|
|
@@ -111,6 +111,10 @@ if (isUser(maybeUser)) {
|
|
|
111
111
|
}
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
Use `optionalKey(...)` for key-level optional properties in `struct`.
|
|
115
|
+
Use `optional(...)` when the key exists but the value itself may be `undefined`.
|
|
116
|
+
Combine them as `optionalKey(optional(guard))` when both are allowed.
|
|
117
|
+
|
|
114
118
|
Composed guards stay reusable:
|
|
115
119
|
`isPositive` can be used standalone or as part of a `struct` definition.
|
|
116
120
|
|
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
|
*
|
|
@@ -323,9 +353,20 @@ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (i
|
|
|
323
353
|
*/
|
|
324
354
|
declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
|
|
325
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Marks a struct schema field as optional at the key level.
|
|
358
|
+
*
|
|
359
|
+
* When used inside `struct`, the property may be absent. If the property exists,
|
|
360
|
+
* its value must satisfy the wrapped guard.
|
|
361
|
+
*
|
|
362
|
+
* @param guard Guard used to validate the property value when the key exists.
|
|
363
|
+
* @returns Schema field marker understood by `struct`.
|
|
364
|
+
*/
|
|
365
|
+
declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSchemaField<G>;
|
|
326
366
|
/**
|
|
327
367
|
* Validates an object against a field-to-guard schema.
|
|
328
|
-
* Keys in the schema are required
|
|
368
|
+
* Keys in the schema are required unless wrapped with `optionalKey`; optionally
|
|
369
|
+
* rejects extra keys when `exact: true`.
|
|
329
370
|
*
|
|
330
371
|
* @param schema Record of property guards.
|
|
331
372
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
@@ -505,4 +546,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
|
|
|
505
546
|
*/
|
|
506
547
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
507
548
|
|
|
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 };
|
|
549
|
+
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, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, 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
|
*
|
|
@@ -323,9 +353,20 @@ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (i
|
|
|
323
353
|
*/
|
|
324
354
|
declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
|
|
325
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Marks a struct schema field as optional at the key level.
|
|
358
|
+
*
|
|
359
|
+
* When used inside `struct`, the property may be absent. If the property exists,
|
|
360
|
+
* its value must satisfy the wrapped guard.
|
|
361
|
+
*
|
|
362
|
+
* @param guard Guard used to validate the property value when the key exists.
|
|
363
|
+
* @returns Schema field marker understood by `struct`.
|
|
364
|
+
*/
|
|
365
|
+
declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSchemaField<G>;
|
|
326
366
|
/**
|
|
327
367
|
* Validates an object against a field-to-guard schema.
|
|
328
|
-
* Keys in the schema are required
|
|
368
|
+
* Keys in the schema are required unless wrapped with `optionalKey`; optionally
|
|
369
|
+
* rejects extra keys when `exact: true`.
|
|
329
370
|
*
|
|
330
371
|
* @param schema Record of property guards.
|
|
331
372
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
@@ -505,4 +546,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
|
|
|
505
546
|
*/
|
|
506
547
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
507
548
|
|
|
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 };
|
|
549
|
+
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, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
|
package/dist/index.js
CHANGED
|
@@ -76,6 +76,7 @@ __export(index_exports, {
|
|
|
76
76
|
oneOf: () => oneOf,
|
|
77
77
|
oneOfValues: () => oneOfValues,
|
|
78
78
|
optional: () => optional,
|
|
79
|
+
optionalKey: () => optionalKey,
|
|
79
80
|
or: () => or,
|
|
80
81
|
predicateToRefine: () => predicateToRefine,
|
|
81
82
|
recordOf: () => recordOf,
|
|
@@ -332,15 +333,44 @@ function recordOf(keyFunction, valueFunction) {
|
|
|
332
333
|
}
|
|
333
334
|
|
|
334
335
|
// src/core/combinators/struct.ts
|
|
335
|
-
var
|
|
336
|
+
var hasOwnKey = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
337
|
+
var isOptionalSchemaField = define(
|
|
338
|
+
// WHY: Optional fields are represented as a small tagged object so `struct`
|
|
339
|
+
// can distinguish schema metadata from plain predicate functions up front.
|
|
340
|
+
(field) => isObject(field) && field.optional === true && typeof field.guard === "function"
|
|
341
|
+
);
|
|
342
|
+
var hasRequiredKeys = (obj, entries) => (
|
|
343
|
+
// WHY: Required fields must be own properties; inherited values should not
|
|
344
|
+
// satisfy a schema because `struct` models object payload shape, not prototype chains.
|
|
345
|
+
entries.every(([key, guard]) => hasOwnKey(obj, key) && guard(obj[key]))
|
|
346
|
+
);
|
|
347
|
+
var hasValidOptionalKeys = (obj, entries) => (
|
|
348
|
+
// WHY: Optional keys are validated only when present. Missing keys stay valid
|
|
349
|
+
// without forcing callers to encode `undefined` into the value guard.
|
|
350
|
+
entries.every(([key, guard]) => !hasOwnKey(obj, key) || guard(obj[key]))
|
|
351
|
+
);
|
|
336
352
|
var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
|
|
353
|
+
function optionalKey(guard) {
|
|
354
|
+
return { optional: true, guard };
|
|
355
|
+
}
|
|
337
356
|
function struct(schema, options) {
|
|
338
|
-
const
|
|
357
|
+
const requiredEntries = [];
|
|
358
|
+
const optionalEntries = [];
|
|
359
|
+
const schemaKeys = [];
|
|
360
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
361
|
+
schemaKeys.push(key);
|
|
362
|
+
if (isOptionalSchemaField(field)) {
|
|
363
|
+
optionalEntries.push([key, field.guard]);
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
requiredEntries.push([key, field]);
|
|
367
|
+
}
|
|
339
368
|
const allowed = options?.exact ? new Set(schemaKeys) : null;
|
|
340
369
|
return (input) => {
|
|
341
370
|
if (!isPlainObject(input)) return false;
|
|
342
371
|
const obj = input;
|
|
343
|
-
if (!hasRequiredKeys(obj,
|
|
372
|
+
if (!hasRequiredKeys(obj, requiredEntries)) return false;
|
|
373
|
+
if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
|
|
344
374
|
if (!allowed) return true;
|
|
345
375
|
return hasOnlyAllowedKeys(obj, allowed);
|
|
346
376
|
};
|
|
@@ -463,6 +493,7 @@ function narrowKeyTo(guard, key) {
|
|
|
463
493
|
oneOf,
|
|
464
494
|
oneOfValues,
|
|
465
495
|
optional,
|
|
496
|
+
optionalKey,
|
|
466
497
|
or,
|
|
467
498
|
predicateToRefine,
|
|
468
499
|
recordOf,
|
package/dist/index.mjs
CHANGED
|
@@ -242,15 +242,44 @@ function recordOf(keyFunction, valueFunction) {
|
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
// src/core/combinators/struct.ts
|
|
245
|
-
var
|
|
245
|
+
var hasOwnKey = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
246
|
+
var isOptionalSchemaField = define(
|
|
247
|
+
// WHY: Optional fields are represented as a small tagged object so `struct`
|
|
248
|
+
// can distinguish schema metadata from plain predicate functions up front.
|
|
249
|
+
(field) => isObject(field) && field.optional === true && typeof field.guard === "function"
|
|
250
|
+
);
|
|
251
|
+
var hasRequiredKeys = (obj, entries) => (
|
|
252
|
+
// WHY: Required fields must be own properties; inherited values should not
|
|
253
|
+
// satisfy a schema because `struct` models object payload shape, not prototype chains.
|
|
254
|
+
entries.every(([key, guard]) => hasOwnKey(obj, key) && guard(obj[key]))
|
|
255
|
+
);
|
|
256
|
+
var hasValidOptionalKeys = (obj, entries) => (
|
|
257
|
+
// WHY: Optional keys are validated only when present. Missing keys stay valid
|
|
258
|
+
// without forcing callers to encode `undefined` into the value guard.
|
|
259
|
+
entries.every(([key, guard]) => !hasOwnKey(obj, key) || guard(obj[key]))
|
|
260
|
+
);
|
|
246
261
|
var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
|
|
262
|
+
function optionalKey(guard) {
|
|
263
|
+
return { optional: true, guard };
|
|
264
|
+
}
|
|
247
265
|
function struct(schema, options) {
|
|
248
|
-
const
|
|
266
|
+
const requiredEntries = [];
|
|
267
|
+
const optionalEntries = [];
|
|
268
|
+
const schemaKeys = [];
|
|
269
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
270
|
+
schemaKeys.push(key);
|
|
271
|
+
if (isOptionalSchemaField(field)) {
|
|
272
|
+
optionalEntries.push([key, field.guard]);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
requiredEntries.push([key, field]);
|
|
276
|
+
}
|
|
249
277
|
const allowed = options?.exact ? new Set(schemaKeys) : null;
|
|
250
278
|
return (input) => {
|
|
251
279
|
if (!isPlainObject(input)) return false;
|
|
252
280
|
const obj = input;
|
|
253
|
-
if (!hasRequiredKeys(obj,
|
|
281
|
+
if (!hasRequiredKeys(obj, requiredEntries)) return false;
|
|
282
|
+
if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
|
|
254
283
|
if (!allowed) return true;
|
|
255
284
|
return hasOnlyAllowedKeys(obj, allowed);
|
|
256
285
|
};
|
|
@@ -372,6 +401,7 @@ export {
|
|
|
372
401
|
oneOf,
|
|
373
402
|
oneOfValues,
|
|
374
403
|
optional,
|
|
404
|
+
optionalKey,
|
|
375
405
|
or,
|
|
376
406
|
predicateToRefine,
|
|
377
407
|
recordOf,
|