is-kit 1.7.4 → 1.8.1
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 +15 -4
- package/dist/index.d.mts +35 -5
- package/dist/index.d.ts +35 -5
- package/dist/index.js +16 -3
- package/dist/index.mjs +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -309,22 +309,33 @@ if (isAdmin(value)) {
|
|
|
309
309
|
|
|
310
310
|
Here are the kinds of problems `is-kit` is especially good at solving:
|
|
311
311
|
|
|
312
|
-
###
|
|
312
|
+
### Typed object guard checks
|
|
313
313
|
|
|
314
314
|
```ts
|
|
315
|
-
import { isNumber, isString, safeParse,
|
|
315
|
+
import { isNumber, isString, optionalKey, safeParse, typedStruct } from 'is-kit';
|
|
316
316
|
|
|
317
|
-
|
|
317
|
+
type PostResponse = ApiResponse<'/posts/{id}', 'get'>;
|
|
318
|
+
|
|
319
|
+
const isPost = typedStruct<PostResponse>()({
|
|
318
320
|
id: isNumber,
|
|
319
|
-
title: isString
|
|
321
|
+
title: isString,
|
|
322
|
+
summary: optionalKey(isString)
|
|
320
323
|
});
|
|
321
324
|
|
|
325
|
+
const payload: unknown = await fetchPost();
|
|
322
326
|
const parsed = safeParse(isPost, payload);
|
|
327
|
+
|
|
323
328
|
if (parsed.valid) {
|
|
324
329
|
renderPost(parsed.value);
|
|
325
330
|
}
|
|
326
331
|
```
|
|
327
332
|
|
|
333
|
+
`typedStruct<T>()` is a small helper for keeping hand-written `struct` guards in
|
|
334
|
+
sync with an existing object type. Optional keys in `T` must still be declared
|
|
335
|
+
with `optionalKey(...)`; this makes drift visible when the target type changes.
|
|
336
|
+
OpenAPI-generated response types are one useful case, but the helper is not an
|
|
337
|
+
OpenAPI validator or schema generator.
|
|
338
|
+
|
|
328
339
|
### Safe array filtering
|
|
329
340
|
|
|
330
341
|
```ts
|
package/dist/index.d.mts
CHANGED
|
@@ -31,20 +31,26 @@ type SchemaField = Predicate<unknown> | OptionalSchemaField<Predicate<unknown>>;
|
|
|
31
31
|
* Object schema consumed by `struct`.
|
|
32
32
|
*/
|
|
33
33
|
type Schema = Readonly<Record<string, SchemaField>>;
|
|
34
|
+
/**
|
|
35
|
+
* Object schema shape preserving concrete keys.
|
|
36
|
+
*/
|
|
37
|
+
type SchemaShape<S extends object> = Readonly<{
|
|
38
|
+
[K in keyof S]: SchemaField;
|
|
39
|
+
}>;
|
|
34
40
|
type Simplify<T> = {
|
|
35
41
|
[K in keyof T]: T[K];
|
|
36
42
|
};
|
|
37
43
|
type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
|
|
38
|
-
type RequiredSchemaKeys<S extends
|
|
44
|
+
type RequiredSchemaKeys<S extends SchemaShape<S>> = {
|
|
39
45
|
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? never : K;
|
|
40
46
|
}[keyof S];
|
|
41
|
-
type OptionalSchemaKeys<S extends
|
|
47
|
+
type OptionalSchemaKeys<S extends SchemaShape<S>> = {
|
|
42
48
|
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? K : never;
|
|
43
49
|
}[keyof S];
|
|
44
50
|
/**
|
|
45
51
|
* Infers the readonly object type produced by a `struct` schema.
|
|
46
52
|
*/
|
|
47
|
-
type InferSchema<S extends
|
|
53
|
+
type InferSchema<S extends SchemaShape<S>> = Simplify<{
|
|
48
54
|
readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
|
|
49
55
|
} & {
|
|
50
56
|
readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
|
|
@@ -549,10 +555,34 @@ declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSc
|
|
|
549
555
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
550
556
|
* @returns Predicate that narrows to the inferred struct type.
|
|
551
557
|
*/
|
|
552
|
-
declare function struct<S extends
|
|
558
|
+
declare function struct<const S extends SchemaShape<S>>(schema: S, options?: {
|
|
553
559
|
exact?: boolean;
|
|
554
560
|
}): Predicate<InferSchema<S>>;
|
|
555
561
|
|
|
562
|
+
type OptionalKeys<T> = {
|
|
563
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
|
564
|
+
}[keyof T];
|
|
565
|
+
type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;
|
|
566
|
+
type TypedStructShape<T extends object> = {
|
|
567
|
+
readonly [K in Extract<RequiredKeys<T>, string>]-?: Predicate<T[K]>;
|
|
568
|
+
} & {
|
|
569
|
+
readonly [K in Extract<OptionalKeys<T>, string>]-?: OptionalSchemaField<Predicate<T[K]>>;
|
|
570
|
+
};
|
|
571
|
+
type NoExtraKeys<S, Shape> = S & {
|
|
572
|
+
readonly [K in Exclude<keyof S, keyof Shape>]: never;
|
|
573
|
+
};
|
|
574
|
+
type TypedStructFields<T extends object, S extends TypedStructShape<T>> = NoExtraKeys<S, TypedStructShape<T>>;
|
|
575
|
+
/**
|
|
576
|
+
* Creates a `struct` builder checked against an existing object type.
|
|
577
|
+
* Optional target keys must also be declared with `optionalKey` so type drift
|
|
578
|
+
* stays visible when the target type changes.
|
|
579
|
+
*
|
|
580
|
+
* @returns Builder that rejects missing, extra, or incompatible struct fields.
|
|
581
|
+
*/
|
|
582
|
+
declare function typedStruct<T extends object>(): <const S extends TypedStructShape<T>>(fields: TypedStructFields<T, S>, options?: {
|
|
583
|
+
exact?: boolean;
|
|
584
|
+
}) => Predicate<InferSchema<TypedStructFields<T, S>>>;
|
|
585
|
+
|
|
556
586
|
/**
|
|
557
587
|
* Validates a fixed-length tuple by applying element-wise guards.
|
|
558
588
|
*
|
|
@@ -614,4 +644,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
|
|
|
614
644
|
*/
|
|
615
645
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
616
646
|
|
|
617
|
-
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, everyArrayValue, everyMapEntry, everyOwnEnumerableEntry, everySetValue, everyTupleValue, 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, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
|
|
647
|
+
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, everyArrayValue, everyMapEntry, everyOwnEnumerableEntry, everySetValue, everyTupleValue, 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, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,20 +31,26 @@ type SchemaField = Predicate<unknown> | OptionalSchemaField<Predicate<unknown>>;
|
|
|
31
31
|
* Object schema consumed by `struct`.
|
|
32
32
|
*/
|
|
33
33
|
type Schema = Readonly<Record<string, SchemaField>>;
|
|
34
|
+
/**
|
|
35
|
+
* Object schema shape preserving concrete keys.
|
|
36
|
+
*/
|
|
37
|
+
type SchemaShape<S extends object> = Readonly<{
|
|
38
|
+
[K in keyof S]: SchemaField;
|
|
39
|
+
}>;
|
|
34
40
|
type Simplify<T> = {
|
|
35
41
|
[K in keyof T]: T[K];
|
|
36
42
|
};
|
|
37
43
|
type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
|
|
38
|
-
type RequiredSchemaKeys<S extends
|
|
44
|
+
type RequiredSchemaKeys<S extends SchemaShape<S>> = {
|
|
39
45
|
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? never : K;
|
|
40
46
|
}[keyof S];
|
|
41
|
-
type OptionalSchemaKeys<S extends
|
|
47
|
+
type OptionalSchemaKeys<S extends SchemaShape<S>> = {
|
|
42
48
|
[K in keyof S]-?: S[K] extends OptionalSchemaField<Predicate<unknown>> ? K : never;
|
|
43
49
|
}[keyof S];
|
|
44
50
|
/**
|
|
45
51
|
* Infers the readonly object type produced by a `struct` schema.
|
|
46
52
|
*/
|
|
47
|
-
type InferSchema<S extends
|
|
53
|
+
type InferSchema<S extends SchemaShape<S>> = Simplify<{
|
|
48
54
|
readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
|
|
49
55
|
} & {
|
|
50
56
|
readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
|
|
@@ -549,10 +555,34 @@ declare function optionalKey<G extends Predicate<unknown>>(guard: G): OptionalSc
|
|
|
549
555
|
* @param options When `{ exact: true }`, disallows properties not in `schema`.
|
|
550
556
|
* @returns Predicate that narrows to the inferred struct type.
|
|
551
557
|
*/
|
|
552
|
-
declare function struct<S extends
|
|
558
|
+
declare function struct<const S extends SchemaShape<S>>(schema: S, options?: {
|
|
553
559
|
exact?: boolean;
|
|
554
560
|
}): Predicate<InferSchema<S>>;
|
|
555
561
|
|
|
562
|
+
type OptionalKeys<T> = {
|
|
563
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
|
564
|
+
}[keyof T];
|
|
565
|
+
type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;
|
|
566
|
+
type TypedStructShape<T extends object> = {
|
|
567
|
+
readonly [K in Extract<RequiredKeys<T>, string>]-?: Predicate<T[K]>;
|
|
568
|
+
} & {
|
|
569
|
+
readonly [K in Extract<OptionalKeys<T>, string>]-?: OptionalSchemaField<Predicate<T[K]>>;
|
|
570
|
+
};
|
|
571
|
+
type NoExtraKeys<S, Shape> = S & {
|
|
572
|
+
readonly [K in Exclude<keyof S, keyof Shape>]: never;
|
|
573
|
+
};
|
|
574
|
+
type TypedStructFields<T extends object, S extends TypedStructShape<T>> = NoExtraKeys<S, TypedStructShape<T>>;
|
|
575
|
+
/**
|
|
576
|
+
* Creates a `struct` builder checked against an existing object type.
|
|
577
|
+
* Optional target keys must also be declared with `optionalKey` so type drift
|
|
578
|
+
* stays visible when the target type changes.
|
|
579
|
+
*
|
|
580
|
+
* @returns Builder that rejects missing, extra, or incompatible struct fields.
|
|
581
|
+
*/
|
|
582
|
+
declare function typedStruct<T extends object>(): <const S extends TypedStructShape<T>>(fields: TypedStructFields<T, S>, options?: {
|
|
583
|
+
exact?: boolean;
|
|
584
|
+
}) => Predicate<InferSchema<TypedStructFields<T, S>>>;
|
|
585
|
+
|
|
556
586
|
/**
|
|
557
587
|
* Validates a fixed-length tuple by applying element-wise guards.
|
|
558
588
|
*
|
|
@@ -614,4 +644,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
|
|
|
614
644
|
*/
|
|
615
645
|
declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
|
|
616
646
|
|
|
617
|
-
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, everyArrayValue, everyMapEntry, everyOwnEnumerableEntry, everySetValue, everyTupleValue, 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, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
|
|
647
|
+
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, everyArrayValue, everyMapEntry, everyOwnEnumerableEntry, everySetValue, everyTupleValue, 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, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
|
package/dist/index.js
CHANGED
|
@@ -93,7 +93,8 @@ __export(index_exports, {
|
|
|
93
93
|
setOf: () => setOf,
|
|
94
94
|
struct: () => struct,
|
|
95
95
|
toBooleanPredicates: () => toBooleanPredicates,
|
|
96
|
-
tupleOf: () => tupleOf
|
|
96
|
+
tupleOf: () => tupleOf,
|
|
97
|
+
typedStruct: () => typedStruct
|
|
97
98
|
});
|
|
98
99
|
module.exports = __toCommonJS(index_exports);
|
|
99
100
|
|
|
@@ -458,7 +459,9 @@ function struct(schema, options) {
|
|
|
458
459
|
const requiredEntries = [];
|
|
459
460
|
const optionalEntries = [];
|
|
460
461
|
const schemaKeys = [];
|
|
461
|
-
for (const
|
|
462
|
+
for (const key in schema) {
|
|
463
|
+
if (!Object.hasOwn(schema, key)) continue;
|
|
464
|
+
const field = schema[key];
|
|
462
465
|
schemaKeys.push(key);
|
|
463
466
|
if (isOptionalSchemaField(field)) {
|
|
464
467
|
optionalEntries.push([key, field.guard]);
|
|
@@ -477,6 +480,15 @@ function struct(schema, options) {
|
|
|
477
480
|
});
|
|
478
481
|
}
|
|
479
482
|
|
|
483
|
+
// src/core/combinators/typed-struct.ts
|
|
484
|
+
function typedStruct() {
|
|
485
|
+
return (fields, options) => (
|
|
486
|
+
// WHY: `typedStruct` keeps `struct` runtime behavior while using the target
|
|
487
|
+
// type only to check that hand-written guard fields stay in sync.
|
|
488
|
+
struct(fields, options)
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
480
492
|
// src/core/combinators/tuple.ts
|
|
481
493
|
function tupleOf(...guards) {
|
|
482
494
|
return define(
|
|
@@ -558,5 +570,6 @@ function tupleOf(...guards) {
|
|
|
558
570
|
setOf,
|
|
559
571
|
struct,
|
|
560
572
|
toBooleanPredicates,
|
|
561
|
-
tupleOf
|
|
573
|
+
tupleOf,
|
|
574
|
+
typedStruct
|
|
562
575
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -359,7 +359,9 @@ function struct(schema, options) {
|
|
|
359
359
|
const requiredEntries = [];
|
|
360
360
|
const optionalEntries = [];
|
|
361
361
|
const schemaKeys = [];
|
|
362
|
-
for (const
|
|
362
|
+
for (const key in schema) {
|
|
363
|
+
if (!Object.hasOwn(schema, key)) continue;
|
|
364
|
+
const field = schema[key];
|
|
363
365
|
schemaKeys.push(key);
|
|
364
366
|
if (isOptionalSchemaField(field)) {
|
|
365
367
|
optionalEntries.push([key, field.guard]);
|
|
@@ -378,6 +380,15 @@ function struct(schema, options) {
|
|
|
378
380
|
});
|
|
379
381
|
}
|
|
380
382
|
|
|
383
|
+
// src/core/combinators/typed-struct.ts
|
|
384
|
+
function typedStruct() {
|
|
385
|
+
return (fields, options) => (
|
|
386
|
+
// WHY: `typedStruct` keeps `struct` runtime behavior while using the target
|
|
387
|
+
// type only to check that hand-written guard fields stay in sync.
|
|
388
|
+
struct(fields, options)
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
381
392
|
// src/core/combinators/tuple.ts
|
|
382
393
|
function tupleOf(...guards) {
|
|
383
394
|
return define(
|
|
@@ -458,5 +469,6 @@ export {
|
|
|
458
469
|
setOf,
|
|
459
470
|
struct,
|
|
460
471
|
toBooleanPredicates,
|
|
461
|
-
tupleOf
|
|
472
|
+
tupleOf,
|
|
473
|
+
typedStruct
|
|
462
474
|
};
|