is-kit 1.7.4 → 1.8.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 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
- ### API response checks
312
+ ### Typed object guard checks
313
313
 
314
314
  ```ts
315
- import { isNumber, isString, safeParse, struct } from 'is-kit';
315
+ import { isNumber, isString, optionalKey, safeParse, typedStruct } from 'is-kit';
316
316
 
317
- const isPost = struct({
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,7 +31,7 @@ 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
- type Simplify<T> = {
34
+ type Simplify$1<T> = {
35
35
  [K in keyof T]: T[K];
36
36
  };
37
37
  type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
@@ -44,7 +44,7 @@ type OptionalSchemaKeys<S extends Schema> = {
44
44
  /**
45
45
  * Infers the readonly object type produced by a `struct` schema.
46
46
  */
47
- type InferSchema<S extends Schema> = Simplify<{
47
+ type InferSchema<S extends Schema> = Simplify$1<{
48
48
  readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
49
49
  } & {
50
50
  readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
@@ -553,6 +553,34 @@ declare function struct<S extends Schema>(schema: S, options?: {
553
553
  exact?: boolean;
554
554
  }): Predicate<InferSchema<S>>;
555
555
 
556
+ type Simplify<T> = {
557
+ [K in keyof T]: T[K];
558
+ };
559
+ type StringKeyOf<T> = Extract<keyof T, string>;
560
+ type OptionalKeys<T> = {
561
+ [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
562
+ }[keyof T];
563
+ type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;
564
+ type TypedStructShape<T extends object> = {
565
+ readonly [K in Extract<RequiredKeys<T>, string>]-?: Predicate<T[K]>;
566
+ } & {
567
+ readonly [K in Extract<OptionalKeys<T>, string>]-?: OptionalSchemaField<Predicate<T[K]>>;
568
+ };
569
+ type NoExtraKeys<S, Shape> = S & {
570
+ readonly [K in Exclude<keyof S, keyof Shape>]: never;
571
+ };
572
+ type TypedStructTarget<T extends object> = Simplify<Readonly<Pick<T, StringKeyOf<T>>>>;
573
+ /**
574
+ * Creates a `struct` builder checked against an existing object type.
575
+ * Optional target keys must also be declared with `optionalKey` so type drift
576
+ * stays visible when the target type changes.
577
+ *
578
+ * @returns Builder that rejects missing, extra, or incompatible struct fields.
579
+ */
580
+ declare function typedStruct<T extends object>(): <const S extends TypedStructShape<T>>(fields: NoExtraKeys<S, TypedStructShape<T>>, options?: {
581
+ exact?: boolean;
582
+ }) => Predicate<TypedStructTarget<T>>;
583
+
556
584
  /**
557
585
  * Validates a fixed-length tuple by applying element-wise guards.
558
586
  *
@@ -614,4 +642,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
614
642
  */
615
643
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
616
644
 
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 };
645
+ 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,7 +31,7 @@ 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
- type Simplify<T> = {
34
+ type Simplify$1<T> = {
35
35
  [K in keyof T]: T[K];
36
36
  };
37
37
  type InferSchemaField<F> = F extends Predicate<unknown> ? GuardedOf<F> : F extends OptionalSchemaField<infer G> ? GuardedOf<G> : never;
@@ -44,7 +44,7 @@ type OptionalSchemaKeys<S extends Schema> = {
44
44
  /**
45
45
  * Infers the readonly object type produced by a `struct` schema.
46
46
  */
47
- type InferSchema<S extends Schema> = Simplify<{
47
+ type InferSchema<S extends Schema> = Simplify$1<{
48
48
  readonly [K in RequiredSchemaKeys<S>]: InferSchemaField<S[K]>;
49
49
  } & {
50
50
  readonly [K in OptionalSchemaKeys<S>]?: InferSchemaField<S[K]>;
@@ -553,6 +553,34 @@ declare function struct<S extends Schema>(schema: S, options?: {
553
553
  exact?: boolean;
554
554
  }): Predicate<InferSchema<S>>;
555
555
 
556
+ type Simplify<T> = {
557
+ [K in keyof T]: T[K];
558
+ };
559
+ type StringKeyOf<T> = Extract<keyof T, string>;
560
+ type OptionalKeys<T> = {
561
+ [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
562
+ }[keyof T];
563
+ type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;
564
+ type TypedStructShape<T extends object> = {
565
+ readonly [K in Extract<RequiredKeys<T>, string>]-?: Predicate<T[K]>;
566
+ } & {
567
+ readonly [K in Extract<OptionalKeys<T>, string>]-?: OptionalSchemaField<Predicate<T[K]>>;
568
+ };
569
+ type NoExtraKeys<S, Shape> = S & {
570
+ readonly [K in Exclude<keyof S, keyof Shape>]: never;
571
+ };
572
+ type TypedStructTarget<T extends object> = Simplify<Readonly<Pick<T, StringKeyOf<T>>>>;
573
+ /**
574
+ * Creates a `struct` builder checked against an existing object type.
575
+ * Optional target keys must also be declared with `optionalKey` so type drift
576
+ * stays visible when the target type changes.
577
+ *
578
+ * @returns Builder that rejects missing, extra, or incompatible struct fields.
579
+ */
580
+ declare function typedStruct<T extends object>(): <const S extends TypedStructShape<T>>(fields: NoExtraKeys<S, TypedStructShape<T>>, options?: {
581
+ exact?: boolean;
582
+ }) => Predicate<TypedStructTarget<T>>;
583
+
556
584
  /**
557
585
  * Validates a fixed-length tuple by applying element-wise guards.
558
586
  *
@@ -614,4 +642,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
614
642
  */
615
643
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
616
644
 
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 };
645
+ 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
 
@@ -477,6 +478,15 @@ function struct(schema, options) {
477
478
  });
478
479
  }
479
480
 
481
+ // src/core/combinators/typed-struct.ts
482
+ function typedStruct() {
483
+ return (fields, options) => (
484
+ // WHY: `typedStruct` keeps `struct` runtime behavior while using the target
485
+ // type only to check that hand-written guard fields stay in sync.
486
+ struct(fields, options)
487
+ );
488
+ }
489
+
480
490
  // src/core/combinators/tuple.ts
481
491
  function tupleOf(...guards) {
482
492
  return define(
@@ -558,5 +568,6 @@ function tupleOf(...guards) {
558
568
  setOf,
559
569
  struct,
560
570
  toBooleanPredicates,
561
- tupleOf
571
+ tupleOf,
572
+ typedStruct
562
573
  });
package/dist/index.mjs CHANGED
@@ -378,6 +378,15 @@ function struct(schema, options) {
378
378
  });
379
379
  }
380
380
 
381
+ // src/core/combinators/typed-struct.ts
382
+ function typedStruct() {
383
+ return (fields, options) => (
384
+ // WHY: `typedStruct` keeps `struct` runtime behavior while using the target
385
+ // type only to check that hand-written guard fields stay in sync.
386
+ struct(fields, options)
387
+ );
388
+ }
389
+
381
390
  // src/core/combinators/tuple.ts
382
391
  function tupleOf(...guards) {
383
392
  return define(
@@ -458,5 +467,6 @@ export {
458
467
  setOf,
459
468
  struct,
460
469
  toBooleanPredicates,
461
- tupleOf
470
+ tupleOf,
471
+ typedStruct
462
472
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "is-kit",
3
- "version": "1.7.4",
3
+ "version": "1.8.0",
4
4
  "description": "Make 'isXXX' easier. Let's make your code type safe and more readable!",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",