is-kit 1.10.0 → 1.11.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 CHANGED
@@ -111,6 +111,69 @@ This is the core idea of `is-kit`:
111
111
  2. Compose them.
112
112
  3. Reuse them anywhere TypeScript narrowing matters.
113
113
 
114
+ ## 🧭 Guard Composition Guide
115
+
116
+ When writing reusable guards with `is-kit`, start from the library primitives:
117
+ use `define` for custom runtime checks, and use logic combinators such as
118
+ `and`, `or`, and `not` when combining existing guards. This keeps the result
119
+ reusable as a named guard and preserves the type-level intent in hover,
120
+ completion, and generated declarations.
121
+
122
+ ```ts
123
+ import {
124
+ and,
125
+ define,
126
+ isNil,
127
+ isNumber,
128
+ isString,
129
+ nullish,
130
+ or,
131
+ predicateToRefine
132
+ } from 'is-kit';
133
+
134
+ const isId = or(isString, isNumber);
135
+ const isNullishString = nullish(isString);
136
+
137
+ const isSlug = define<string>(
138
+ (value) => isString(value) && /^[a-z0-9-]+$/.test(value)
139
+ );
140
+
141
+ const isPositiveNumber = and(
142
+ isNumber,
143
+ predicateToRefine<number>((value) => value > 0)
144
+ );
145
+
146
+ isNil(null); // true
147
+ isNil(undefined); // true
148
+ isId('user-1'); // true
149
+ isNullishString(undefined); // true
150
+ isSlug('release-110'); // true
151
+ isPositiveNumber(1); // true
152
+ ```
153
+
154
+ Prefer these forms when generating or reviewing code:
155
+
156
+ ```ts
157
+ declare const value: unknown;
158
+
159
+ // Prefer
160
+ const isId = or(isString, isNumber);
161
+ const isMaybeName = nullish(isString);
162
+ const isSlug = define<string>(
163
+ (value) => isString(value) && /^[a-z0-9-]+$/.test(value)
164
+ );
165
+
166
+ // Avoid
167
+ const isId = (value: unknown) => isString(value) || isNumber(value);
168
+ const isMaybeName = (value: unknown) => value == null || isString(value);
169
+ const isSlug = (value: unknown): value is string =>
170
+ isString(value) && /^[a-z0-9-]+$/.test(value);
171
+ ```
172
+
173
+ For AI agents or repository-wide conventions, copy
174
+ [docs/agent-rules.md](./docs/agent-rules.md) into the consumer repository's
175
+ agent instructions.
176
+
114
177
  ## ⌚ A 30-second Mental Model
115
178
 
116
179
  If you are new to the library, these are the pieces to remember:
@@ -270,6 +333,17 @@ const isDefinedString = required(optional(isString));
270
333
  const isNonNullString = nonNull(nullable(isString));
271
334
  ```
272
335
 
336
+ For a plain "is it `null` or `undefined`?" check, reach for `isNil` instead of
337
+ hand-rolling `isNull(x) || isUndefined(x)`:
338
+
339
+ ```ts
340
+ import { isNil } from 'is-kit';
341
+
342
+ isNil(null); // true
343
+ isNil(undefined); // true
344
+ isNil(0); // false
345
+ ```
346
+
273
347
  ### 8. Parse or assert unknown input
274
348
 
275
349
  Use `safeParse` when you want a result object, and `assert` when invalid data should stop execution.
@@ -434,7 +508,7 @@ The library is organized around a few small building blocks:
434
508
  - **Object shapes**: `struct`, `optionalKey`, `hasKey`, `hasKeys`, `narrowKeyTo`
435
509
  - **Collections**: `arrayOf`, `nonEmptyArrayOf`, `tupleOf`, `setOf`, `mapOf`, `recordOf`
436
510
  - **Literals**: `oneOfValues`, `equals`, `equalsBy`, `equalsKey`
437
- - **Nullish handling**: `nullable`, `nonNull`, `nullish`, `optional`, `required`
511
+ - **Nullish handling**: `isNil`, `nullable`, `nonNull`, `nullish`, `optional`, `required`
438
512
  - **Result helpers**: `safeParse`, `safeParseWith`, `safeJsonParse`, `assert`
439
513
 
440
514
  For the full API list and dedicated pages, use the docs site below.
package/dist/index.d.mts CHANGED
@@ -1,3 +1,11 @@
1
+ /**
2
+ * is-kit guard authoring guide:
3
+ * - Use define<T>(...) for reusable custom runtime checks.
4
+ * - Use and, andAll, or, and not to compose existing guards instead of
5
+ * hand-written boolean wrappers.
6
+ * - Use nullable, optional, or nullish to widen guards for nullish values.
7
+ * - Use struct or typedStruct for object-shape guards.
8
+ */
1
9
  type Predicate<T> = (value: unknown) => value is T;
2
10
  type Refinement<A, B extends A> = (value: A) => value is B;
3
11
  type Guard<T> = Predicate<T>;
@@ -69,12 +77,18 @@ declare function assert<A, B extends A>(refine: Refine<A, B>, value: A, message?
69
77
 
70
78
  /**
71
79
  * Wraps a user function as a typed predicate.
80
+ * Prefer `define<T>(...)` when creating a reusable custom guard from a runtime
81
+ * boolean check.
72
82
  *
73
83
  * Note: The correctness of the predicate is the caller's responsibility.
74
84
  * Its result is coerced to a boolean using `!!` for consistent guard behavior.
75
85
  *
76
86
  * @param fn Function that returns truthy when the value matches the target shape.
77
87
  * @returns Predicate narrowing to the intended type when it returns true.
88
+ * @example
89
+ * const isSlug = define<string>(
90
+ * (value) => isString(value) && /^[a-z0-9-]+$/.test(value)
91
+ * );
78
92
  */
79
93
  declare function define<T>(fn: (value: unknown) => value is T): Predicate<T>;
80
94
  declare function define<T>(fn: (value: unknown) => boolean): Predicate<T>;
@@ -146,49 +160,76 @@ declare function lazy<T>(factory: () => Predicate<T>): Predicate<T>;
146
160
 
147
161
  /**
148
162
  * Combines a precondition guard with an additional refinement to narrow the type.
163
+ * Prefer this over hand-written `precondition(x) && condition(x)` when the
164
+ * composed predicate should be reused as a guard.
149
165
  *
150
166
  * @param precondition Broad guard evaluated first; short-circuits on failure.
151
167
  * @param condition Refinement evaluated only when `precondition` passes.
152
168
  * @returns Predicate that narrows the input to a subtype.
169
+ * @example
170
+ * const isPositiveNumber = and(
171
+ * isNumber,
172
+ * predicateToRefine<number>((value) => value > 0)
173
+ * );
174
+ * @see andAll
153
175
  */
154
176
  declare function and<A, B extends A>(precondition: Guard<A>, condition: Refine<A, B>): Predicate<B>;
155
177
  /**
156
178
  * Chains a sequence of refinements after a precondition, returning the final guard type.
179
+ * Use this instead of nested `&&` checks when each step should keep narrowing
180
+ * the next refinement.
157
181
  *
158
182
  * @param precondition Initial guard applied first.
159
183
  * @param steps Subsequent refinements applied in order.
160
184
  * @returns Guard reflecting the result of the refinement chain.
185
+ * @example
186
+ * const isPublicTitle = andAll(isString, minLength(4), startsWithPublic);
187
+ * @see and
161
188
  */
162
189
  declare function andAll<A>(precondition: Guard<A>): Guard<A>;
163
190
  declare function andAll<A, B extends A>(precondition: Guard<A>, step1: Refine<A, B>): Guard<B>;
164
191
  declare function andAll<A, B extends A, C extends B>(precondition: Guard<A>, step1: Refine<A, B>, step2: Refine<B, C>): Guard<C>;
165
192
  /**
166
193
  * Logical OR over multiple guards.
194
+ * Prefer this over hand-written `guardA(x) || guardB(x)` when the composed
195
+ * predicate should be reused as a guard.
167
196
  *
168
197
  * @param guards Guards to evaluate; passes if any guard passes.
169
198
  * @returns Guard for the union of all guarded types.
199
+ * @example
200
+ * const isId = or(isString, isNumber);
201
+ * @see oneOf
170
202
  */
171
203
  declare function or<P extends readonly Guard<unknown>[]>(...guards: P): Guard<OutOfGuards<P>>;
172
204
  /**
173
205
  * Adapts a guard so it can be used as a refinement within a known supertype.
174
206
  *
175
207
  * @returns Function that converts a `Guard<T>` into a `Refine<A, T>` when `T extends A`.
208
+ * @see and
176
209
  */
177
210
  declare function guardIn<A>(): <T extends A>(guard: Guard<T>) => Refine<A, T>;
178
211
  /**
179
212
  * Logical negation of a guard/refinement.
213
+ * Use this when a negated predicate should be named and reused.
180
214
  *
181
215
  * @param guard Guard or refinement to negate.
182
216
  * @returns Refinement excluding the guarded subtype from the input type.
217
+ * @example
218
+ * const isPresent = not(isNil);
183
219
  */
184
220
  declare function not<A, T>(guard: Guard<T>): Refine<A, Exclude<A, Extract<A, T>>>;
185
221
  declare function not<A, B extends A>(refine: Refine<A, B>): Refine<A, Exclude<A, B>>;
186
222
 
187
223
  /**
188
224
  * Allows `null` in addition to values accepted by the given guard/refinement.
225
+ * Use this instead of hand-writing `value === null || guard(value)` when the
226
+ * widened predicate should stay reusable.
189
227
  *
190
228
  * @param guard Guard/refinement for the base type.
191
229
  * @returns Guard/refinement widened to include `null`.
230
+ * @example
231
+ * const isNullableString = nullable(isString);
232
+ * @see nullish
192
233
  */
193
234
  declare function nullable<T>(guard: Guard<T>): Guard<T | null>;
194
235
  declare function nullable<A, B extends A>(refine: Refine<A, B>): Refine<A | null, B | null>;
@@ -197,22 +238,33 @@ declare function nullable<A, B extends A>(refine: Refine<A, B>): Refine<A | null
197
238
  *
198
239
  * @param guard Guard/refinement possibly including `null`.
199
240
  * @returns Guard/refinement with `null` excluded.
241
+ * @example
242
+ * const isNonNullString = nonNull(nullable(isString));
200
243
  */
201
244
  declare function nonNull<T>(guard: Guard<T>): Guard<Exclude<T, null>>;
202
245
  declare function nonNull<A, B extends A>(refine: Refine<A, B>): Refine<Exclude<A, null>, Exclude<B, null>>;
203
246
  /**
204
247
  * Allows `null` or `undefined` in addition to values accepted by the guard.
248
+ * Use this instead of hand-writing `isNil(value) || guard(value)` when widening
249
+ * another guard.
205
250
  *
206
251
  * @param guard Guard/refinement for the base type.
207
252
  * @returns Guard/refinement widened to include `null | undefined`.
253
+ * @example
254
+ * const isNullishString = nullish(isString);
255
+ * @see isNil
208
256
  */
209
257
  declare function nullish<T>(guard: Guard<T>): Guard<T | null | undefined>;
210
258
  declare function nullish<A, B extends A>(refine: Refine<A, B>): Refine<A | null | undefined, B | null | undefined>;
211
259
  /**
212
260
  * Allows `undefined` in addition to values accepted by the guard.
261
+ * Use this for value-level optionality. For optional object keys in `struct`,
262
+ * use `optionalKey(...)`.
213
263
  *
214
264
  * @param guard Guard/refinement for the base type.
215
265
  * @returns Guard/refinement widened to include `undefined`.
266
+ * @example
267
+ * const isOptionalString = optional(isString);
216
268
  */
217
269
  declare function optional<T>(guard: Guard<T>): Guard<T | undefined>;
218
270
  declare function optional<A, B extends A>(refine: Refine<A, B>): Refine<A | undefined, B | undefined>;
@@ -221,6 +273,8 @@ declare function optional<A, B extends A>(refine: Refine<A, B>): Refine<A | unde
221
273
  *
222
274
  * @param guard Guard/refinement that may accept `undefined`.
223
275
  * @returns Guard/refinement with `undefined` removed.
276
+ * @example
277
+ * const isRequiredString = required(optional(isString));
224
278
  */
225
279
  declare function required<T>(guard: Guard<T | undefined>): Guard<T>;
226
280
  declare function required<A, B extends A>(refine: Refine<A | undefined, B | undefined>): Refine<A, B>;
@@ -351,15 +405,38 @@ declare const isSymbol: Predicate<symbol>;
351
405
  /**
352
406
  * Checks whether a value is exactly `undefined`.
353
407
  *
408
+ * For reusable nullish checks, use {@link isNil} or compose a named guard with
409
+ * {@link or} once and reuse it.
410
+ *
354
411
  * @returns Predicate narrowing to `undefined`.
412
+ * @see isNil
355
413
  */
356
414
  declare const isUndefined: Predicate<undefined>;
357
415
  /**
358
416
  * Checks whether a value is exactly `null`.
359
417
  *
418
+ * For reusable nullish checks, use {@link isNil} or compose a named guard with
419
+ * {@link or} once and reuse it.
420
+ *
360
421
  * @returns Predicate narrowing to `null`.
422
+ * @see isNil
361
423
  */
362
424
  declare const isNull: Predicate<null>;
425
+ /**
426
+ * Checks whether a value is `null` or `undefined` (nullish).
427
+ *
428
+ * Prefer this over hand-rolling `isNull(x) || isUndefined(x)`: it is the same
429
+ * check expressed once. To widen an existing guard so it also accepts nullish
430
+ * values, use {@link nullish} instead.
431
+ *
432
+ * @returns Predicate narrowing to `null | undefined`.
433
+ * @example
434
+ * isNil(null); // true
435
+ * isNil(undefined); // true
436
+ * isNil(0); // false
437
+ * @see or
438
+ */
439
+ declare const isNil: Guard<null | undefined>;
363
440
  /**
364
441
  * Checks whether a value is a JavaScript primitive.
365
442
  *
@@ -485,6 +562,12 @@ declare const isURL: Guard<URL>;
485
562
  * @returns Predicate narrowing to `Blob` when supported; otherwise always false.
486
563
  */
487
564
  declare const isBlob: Guard<Blob>;
565
+ /**
566
+ * Checks whether a value is a `File` (in environments with File available).
567
+ *
568
+ * @returns Predicate narrowing to `File` when supported; otherwise always false.
569
+ */
570
+ declare const isFile: Guard<File>;
488
571
  /**
489
572
  * Creates a guard that checks whether a value is an instance of `constructor`.
490
573
  *
@@ -613,6 +696,7 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
613
696
  readonly [K in keyof Fs]: GuardedOf<Fs[K]>;
614
697
  }>;
615
698
 
699
+ type BooleanPredicate<T> = (value: T) => boolean;
616
700
  /**
617
701
  * Checks whether every array element satisfies the provided predicate.
618
702
  *
@@ -620,7 +704,7 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
620
704
  * @param predicate Predicate applied to each element.
621
705
  * @returns Whether all elements satisfy `predicate`.
622
706
  */
623
- declare const everyArrayValue: (values: readonly unknown[], predicate: (value: unknown) => boolean) => boolean;
707
+ declare const everyArrayValue: (values: readonly unknown[], predicate: BooleanPredicate<unknown>) => boolean;
624
708
  /**
625
709
  * Checks whether a tuple matches the provided element predicates in order.
626
710
  *
@@ -628,7 +712,7 @@ declare const everyArrayValue: (values: readonly unknown[], predicate: (value: u
628
712
  * @param predicates Predicates aligned to each tuple index.
629
713
  * @returns Whether lengths match and each index passes.
630
714
  */
631
- declare const everyTupleValue: (values: readonly unknown[], predicates: readonly ((value: unknown) => boolean)[]) => boolean;
715
+ declare const everyTupleValue: (values: readonly unknown[], predicates: readonly BooleanPredicate<unknown>[]) => boolean;
632
716
  /**
633
717
  * Checks whether every set value satisfies the provided predicate.
634
718
  *
@@ -636,7 +720,7 @@ declare const everyTupleValue: (values: readonly unknown[], predicates: readonly
636
720
  * @param predicate Predicate applied to each value.
637
721
  * @returns Whether all set values satisfy `predicate`.
638
722
  */
639
- declare const everySetValue: (values: ReadonlySet<unknown>, predicate: (value: unknown) => boolean) => boolean;
723
+ declare const everySetValue: (values: ReadonlySet<unknown>, predicate: BooleanPredicate<unknown>) => boolean;
640
724
  /**
641
725
  * Checks whether every map entry satisfies the provided key and value predicates.
642
726
  *
@@ -645,7 +729,7 @@ declare const everySetValue: (values: ReadonlySet<unknown>, predicate: (value: u
645
729
  * @param valuePredicate Predicate applied to each value.
646
730
  * @returns Whether all keys and values satisfy their predicates.
647
731
  */
648
- declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicate: (key: unknown) => boolean, valuePredicate: (value: unknown) => boolean) => boolean;
732
+ declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicate: BooleanPredicate<unknown>, valuePredicate: BooleanPredicate<unknown>) => boolean;
649
733
  /**
650
734
  * Checks whether every own enumerable string key/value pair satisfies the provided predicates.
651
735
  *
@@ -654,7 +738,7 @@ declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicat
654
738
  * @param valuePredicate Predicate applied to each corresponding value.
655
739
  * @returns Whether all enumerable entries satisfy their predicates.
656
740
  */
657
- declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPredicate: (key: string) => boolean, valuePredicate: (value: unknown) => boolean) => boolean;
741
+ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPredicate: BooleanPredicate<string>, valuePredicate: BooleanPredicate<unknown>) => boolean;
658
742
 
659
743
  /**
660
744
  * Converts predicates to plain boolean predicates for iteration helpers.
@@ -664,4 +748,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
664
748
  */
665
749
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
666
750
 
667
- 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, lazy, mapOf, narrowKeyTo, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeJsonParse, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
751
+ 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, isFile, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNil, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, lazy, mapOf, narrowKeyTo, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeJsonParse, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,11 @@
1
+ /**
2
+ * is-kit guard authoring guide:
3
+ * - Use define<T>(...) for reusable custom runtime checks.
4
+ * - Use and, andAll, or, and not to compose existing guards instead of
5
+ * hand-written boolean wrappers.
6
+ * - Use nullable, optional, or nullish to widen guards for nullish values.
7
+ * - Use struct or typedStruct for object-shape guards.
8
+ */
1
9
  type Predicate<T> = (value: unknown) => value is T;
2
10
  type Refinement<A, B extends A> = (value: A) => value is B;
3
11
  type Guard<T> = Predicate<T>;
@@ -69,12 +77,18 @@ declare function assert<A, B extends A>(refine: Refine<A, B>, value: A, message?
69
77
 
70
78
  /**
71
79
  * Wraps a user function as a typed predicate.
80
+ * Prefer `define<T>(...)` when creating a reusable custom guard from a runtime
81
+ * boolean check.
72
82
  *
73
83
  * Note: The correctness of the predicate is the caller's responsibility.
74
84
  * Its result is coerced to a boolean using `!!` for consistent guard behavior.
75
85
  *
76
86
  * @param fn Function that returns truthy when the value matches the target shape.
77
87
  * @returns Predicate narrowing to the intended type when it returns true.
88
+ * @example
89
+ * const isSlug = define<string>(
90
+ * (value) => isString(value) && /^[a-z0-9-]+$/.test(value)
91
+ * );
78
92
  */
79
93
  declare function define<T>(fn: (value: unknown) => value is T): Predicate<T>;
80
94
  declare function define<T>(fn: (value: unknown) => boolean): Predicate<T>;
@@ -146,49 +160,76 @@ declare function lazy<T>(factory: () => Predicate<T>): Predicate<T>;
146
160
 
147
161
  /**
148
162
  * Combines a precondition guard with an additional refinement to narrow the type.
163
+ * Prefer this over hand-written `precondition(x) && condition(x)` when the
164
+ * composed predicate should be reused as a guard.
149
165
  *
150
166
  * @param precondition Broad guard evaluated first; short-circuits on failure.
151
167
  * @param condition Refinement evaluated only when `precondition` passes.
152
168
  * @returns Predicate that narrows the input to a subtype.
169
+ * @example
170
+ * const isPositiveNumber = and(
171
+ * isNumber,
172
+ * predicateToRefine<number>((value) => value > 0)
173
+ * );
174
+ * @see andAll
153
175
  */
154
176
  declare function and<A, B extends A>(precondition: Guard<A>, condition: Refine<A, B>): Predicate<B>;
155
177
  /**
156
178
  * Chains a sequence of refinements after a precondition, returning the final guard type.
179
+ * Use this instead of nested `&&` checks when each step should keep narrowing
180
+ * the next refinement.
157
181
  *
158
182
  * @param precondition Initial guard applied first.
159
183
  * @param steps Subsequent refinements applied in order.
160
184
  * @returns Guard reflecting the result of the refinement chain.
185
+ * @example
186
+ * const isPublicTitle = andAll(isString, minLength(4), startsWithPublic);
187
+ * @see and
161
188
  */
162
189
  declare function andAll<A>(precondition: Guard<A>): Guard<A>;
163
190
  declare function andAll<A, B extends A>(precondition: Guard<A>, step1: Refine<A, B>): Guard<B>;
164
191
  declare function andAll<A, B extends A, C extends B>(precondition: Guard<A>, step1: Refine<A, B>, step2: Refine<B, C>): Guard<C>;
165
192
  /**
166
193
  * Logical OR over multiple guards.
194
+ * Prefer this over hand-written `guardA(x) || guardB(x)` when the composed
195
+ * predicate should be reused as a guard.
167
196
  *
168
197
  * @param guards Guards to evaluate; passes if any guard passes.
169
198
  * @returns Guard for the union of all guarded types.
199
+ * @example
200
+ * const isId = or(isString, isNumber);
201
+ * @see oneOf
170
202
  */
171
203
  declare function or<P extends readonly Guard<unknown>[]>(...guards: P): Guard<OutOfGuards<P>>;
172
204
  /**
173
205
  * Adapts a guard so it can be used as a refinement within a known supertype.
174
206
  *
175
207
  * @returns Function that converts a `Guard<T>` into a `Refine<A, T>` when `T extends A`.
208
+ * @see and
176
209
  */
177
210
  declare function guardIn<A>(): <T extends A>(guard: Guard<T>) => Refine<A, T>;
178
211
  /**
179
212
  * Logical negation of a guard/refinement.
213
+ * Use this when a negated predicate should be named and reused.
180
214
  *
181
215
  * @param guard Guard or refinement to negate.
182
216
  * @returns Refinement excluding the guarded subtype from the input type.
217
+ * @example
218
+ * const isPresent = not(isNil);
183
219
  */
184
220
  declare function not<A, T>(guard: Guard<T>): Refine<A, Exclude<A, Extract<A, T>>>;
185
221
  declare function not<A, B extends A>(refine: Refine<A, B>): Refine<A, Exclude<A, B>>;
186
222
 
187
223
  /**
188
224
  * Allows `null` in addition to values accepted by the given guard/refinement.
225
+ * Use this instead of hand-writing `value === null || guard(value)` when the
226
+ * widened predicate should stay reusable.
189
227
  *
190
228
  * @param guard Guard/refinement for the base type.
191
229
  * @returns Guard/refinement widened to include `null`.
230
+ * @example
231
+ * const isNullableString = nullable(isString);
232
+ * @see nullish
192
233
  */
193
234
  declare function nullable<T>(guard: Guard<T>): Guard<T | null>;
194
235
  declare function nullable<A, B extends A>(refine: Refine<A, B>): Refine<A | null, B | null>;
@@ -197,22 +238,33 @@ declare function nullable<A, B extends A>(refine: Refine<A, B>): Refine<A | null
197
238
  *
198
239
  * @param guard Guard/refinement possibly including `null`.
199
240
  * @returns Guard/refinement with `null` excluded.
241
+ * @example
242
+ * const isNonNullString = nonNull(nullable(isString));
200
243
  */
201
244
  declare function nonNull<T>(guard: Guard<T>): Guard<Exclude<T, null>>;
202
245
  declare function nonNull<A, B extends A>(refine: Refine<A, B>): Refine<Exclude<A, null>, Exclude<B, null>>;
203
246
  /**
204
247
  * Allows `null` or `undefined` in addition to values accepted by the guard.
248
+ * Use this instead of hand-writing `isNil(value) || guard(value)` when widening
249
+ * another guard.
205
250
  *
206
251
  * @param guard Guard/refinement for the base type.
207
252
  * @returns Guard/refinement widened to include `null | undefined`.
253
+ * @example
254
+ * const isNullishString = nullish(isString);
255
+ * @see isNil
208
256
  */
209
257
  declare function nullish<T>(guard: Guard<T>): Guard<T | null | undefined>;
210
258
  declare function nullish<A, B extends A>(refine: Refine<A, B>): Refine<A | null | undefined, B | null | undefined>;
211
259
  /**
212
260
  * Allows `undefined` in addition to values accepted by the guard.
261
+ * Use this for value-level optionality. For optional object keys in `struct`,
262
+ * use `optionalKey(...)`.
213
263
  *
214
264
  * @param guard Guard/refinement for the base type.
215
265
  * @returns Guard/refinement widened to include `undefined`.
266
+ * @example
267
+ * const isOptionalString = optional(isString);
216
268
  */
217
269
  declare function optional<T>(guard: Guard<T>): Guard<T | undefined>;
218
270
  declare function optional<A, B extends A>(refine: Refine<A, B>): Refine<A | undefined, B | undefined>;
@@ -221,6 +273,8 @@ declare function optional<A, B extends A>(refine: Refine<A, B>): Refine<A | unde
221
273
  *
222
274
  * @param guard Guard/refinement that may accept `undefined`.
223
275
  * @returns Guard/refinement with `undefined` removed.
276
+ * @example
277
+ * const isRequiredString = required(optional(isString));
224
278
  */
225
279
  declare function required<T>(guard: Guard<T | undefined>): Guard<T>;
226
280
  declare function required<A, B extends A>(refine: Refine<A | undefined, B | undefined>): Refine<A, B>;
@@ -351,15 +405,38 @@ declare const isSymbol: Predicate<symbol>;
351
405
  /**
352
406
  * Checks whether a value is exactly `undefined`.
353
407
  *
408
+ * For reusable nullish checks, use {@link isNil} or compose a named guard with
409
+ * {@link or} once and reuse it.
410
+ *
354
411
  * @returns Predicate narrowing to `undefined`.
412
+ * @see isNil
355
413
  */
356
414
  declare const isUndefined: Predicate<undefined>;
357
415
  /**
358
416
  * Checks whether a value is exactly `null`.
359
417
  *
418
+ * For reusable nullish checks, use {@link isNil} or compose a named guard with
419
+ * {@link or} once and reuse it.
420
+ *
360
421
  * @returns Predicate narrowing to `null`.
422
+ * @see isNil
361
423
  */
362
424
  declare const isNull: Predicate<null>;
425
+ /**
426
+ * Checks whether a value is `null` or `undefined` (nullish).
427
+ *
428
+ * Prefer this over hand-rolling `isNull(x) || isUndefined(x)`: it is the same
429
+ * check expressed once. To widen an existing guard so it also accepts nullish
430
+ * values, use {@link nullish} instead.
431
+ *
432
+ * @returns Predicate narrowing to `null | undefined`.
433
+ * @example
434
+ * isNil(null); // true
435
+ * isNil(undefined); // true
436
+ * isNil(0); // false
437
+ * @see or
438
+ */
439
+ declare const isNil: Guard<null | undefined>;
363
440
  /**
364
441
  * Checks whether a value is a JavaScript primitive.
365
442
  *
@@ -485,6 +562,12 @@ declare const isURL: Guard<URL>;
485
562
  * @returns Predicate narrowing to `Blob` when supported; otherwise always false.
486
563
  */
487
564
  declare const isBlob: Guard<Blob>;
565
+ /**
566
+ * Checks whether a value is a `File` (in environments with File available).
567
+ *
568
+ * @returns Predicate narrowing to `File` when supported; otherwise always false.
569
+ */
570
+ declare const isFile: Guard<File>;
488
571
  /**
489
572
  * Creates a guard that checks whether a value is an instance of `constructor`.
490
573
  *
@@ -613,6 +696,7 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
613
696
  readonly [K in keyof Fs]: GuardedOf<Fs[K]>;
614
697
  }>;
615
698
 
699
+ type BooleanPredicate<T> = (value: T) => boolean;
616
700
  /**
617
701
  * Checks whether every array element satisfies the provided predicate.
618
702
  *
@@ -620,7 +704,7 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
620
704
  * @param predicate Predicate applied to each element.
621
705
  * @returns Whether all elements satisfy `predicate`.
622
706
  */
623
- declare const everyArrayValue: (values: readonly unknown[], predicate: (value: unknown) => boolean) => boolean;
707
+ declare const everyArrayValue: (values: readonly unknown[], predicate: BooleanPredicate<unknown>) => boolean;
624
708
  /**
625
709
  * Checks whether a tuple matches the provided element predicates in order.
626
710
  *
@@ -628,7 +712,7 @@ declare const everyArrayValue: (values: readonly unknown[], predicate: (value: u
628
712
  * @param predicates Predicates aligned to each tuple index.
629
713
  * @returns Whether lengths match and each index passes.
630
714
  */
631
- declare const everyTupleValue: (values: readonly unknown[], predicates: readonly ((value: unknown) => boolean)[]) => boolean;
715
+ declare const everyTupleValue: (values: readonly unknown[], predicates: readonly BooleanPredicate<unknown>[]) => boolean;
632
716
  /**
633
717
  * Checks whether every set value satisfies the provided predicate.
634
718
  *
@@ -636,7 +720,7 @@ declare const everyTupleValue: (values: readonly unknown[], predicates: readonly
636
720
  * @param predicate Predicate applied to each value.
637
721
  * @returns Whether all set values satisfy `predicate`.
638
722
  */
639
- declare const everySetValue: (values: ReadonlySet<unknown>, predicate: (value: unknown) => boolean) => boolean;
723
+ declare const everySetValue: (values: ReadonlySet<unknown>, predicate: BooleanPredicate<unknown>) => boolean;
640
724
  /**
641
725
  * Checks whether every map entry satisfies the provided key and value predicates.
642
726
  *
@@ -645,7 +729,7 @@ declare const everySetValue: (values: ReadonlySet<unknown>, predicate: (value: u
645
729
  * @param valuePredicate Predicate applied to each value.
646
730
  * @returns Whether all keys and values satisfy their predicates.
647
731
  */
648
- declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicate: (key: unknown) => boolean, valuePredicate: (value: unknown) => boolean) => boolean;
732
+ declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicate: BooleanPredicate<unknown>, valuePredicate: BooleanPredicate<unknown>) => boolean;
649
733
  /**
650
734
  * Checks whether every own enumerable string key/value pair satisfies the provided predicates.
651
735
  *
@@ -654,7 +738,7 @@ declare const everyMapEntry: (values: ReadonlyMap<unknown, unknown>, keyPredicat
654
738
  * @param valuePredicate Predicate applied to each corresponding value.
655
739
  * @returns Whether all enumerable entries satisfy their predicates.
656
740
  */
657
- declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPredicate: (key: string) => boolean, valuePredicate: (value: unknown) => boolean) => boolean;
741
+ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPredicate: BooleanPredicate<string>, valuePredicate: BooleanPredicate<unknown>) => boolean;
658
742
 
659
743
  /**
660
744
  * Converts predicates to plain boolean predicates for iteration helpers.
@@ -664,4 +748,4 @@ declare const everyOwnEnumerableEntry: (values: Record<string, unknown>, keyPred
664
748
  */
665
749
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
666
750
 
667
- 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, lazy, mapOf, narrowKeyTo, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeJsonParse, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
751
+ 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, isFile, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNil, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, lazy, mapOf, narrowKeyTo, nonEmptyArrayOf, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeJsonParse, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf, typedStruct };
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ __export(index_exports, {
45
45
  isDataView: () => isDataView,
46
46
  isDate: () => isDate,
47
47
  isError: () => isError,
48
+ isFile: () => isFile,
48
49
  isFiniteNumber: () => isFiniteNumber,
49
50
  isFunction: () => isFunction,
50
51
  isInfiniteNumber: () => isInfiniteNumber,
@@ -54,6 +55,7 @@ __export(index_exports, {
54
55
  isMap: () => isMap,
55
56
  isNaN: () => isNaN,
56
57
  isNegative: () => isNegative,
58
+ isNil: () => isNil,
57
59
  isNull: () => isNull,
58
60
  isNumber: () => isNumber,
59
61
  isNumberPrimitive: () => isNumberPrimitive,
@@ -112,6 +114,42 @@ function define(fn) {
112
114
  return (value) => !!fn(value);
113
115
  }
114
116
 
117
+ // src/utils/own-properties.ts
118
+ var hasOwnPropertyKey = (value, key) => Object.hasOwn(value, key);
119
+ var hasOwnPropertyKeys = (value, keys) => keys.every((key) => hasOwnPropertyKey(value, key));
120
+
121
+ // src/utils/guard-collections.ts
122
+ var everyIterableValue = (values, predicate) => {
123
+ for (const value of values) {
124
+ if (!predicate(value)) return false;
125
+ }
126
+ return true;
127
+ };
128
+ var everyKeyValueEntry = (entries, predicate) => {
129
+ for (const [key, value] of entries) {
130
+ if (!predicate(key, value)) return false;
131
+ }
132
+ return true;
133
+ };
134
+ var everyArrayValue = (values, predicate) => everyIterableValue(values, predicate);
135
+ var everyTupleValue = (values, predicates) => {
136
+ if (values.length !== predicates.length) return false;
137
+ for (let index = 0; index < predicates.length; index += 1) {
138
+ const predicate = predicates[index];
139
+ if (!predicate(values[index])) return false;
140
+ }
141
+ return true;
142
+ };
143
+ var everySetValue = (values, predicate) => everyIterableValue(values, predicate);
144
+ var everyMapEntry = (values, keyPredicate, valuePredicate) => everyKeyValueEntry(
145
+ values,
146
+ (key, value) => keyPredicate(key) && valuePredicate(value)
147
+ );
148
+ var everyOwnEnumerableEntry = (values, keyPredicate, valuePredicate) => everyIterableValue(
149
+ Object.keys(values),
150
+ (key) => keyPredicate(key) && valuePredicate(values[key])
151
+ );
152
+
115
153
  // src/utils/object-tags.ts
116
154
  var objectToString = Object.prototype.toString;
117
155
  var OBJECT_TAG_DATE = "[object Date]";
@@ -125,6 +163,9 @@ var OBJECT_TAG_DATA_VIEW = "[object DataView]";
125
163
  var OBJECT_TAG_ERROR = "[object Error]";
126
164
  var getTag = (value) => objectToString.call(value);
127
165
 
166
+ // src/utils/to-boolean-predicates.ts
167
+ var toBooleanPredicates = (predicates) => predicates;
168
+
128
169
  // src/core/object.ts
129
170
  var defineTagGuard = (tag) => define((value) => getTag(value) === tag);
130
171
  var defineOptionalInstanceGuard = (constructor) => constructor === void 0 ? define(() => false) : define(
@@ -177,6 +218,9 @@ var isURL = defineOptionalInstanceGuard(
177
218
  var isBlob = defineOptionalInstanceGuard(
178
219
  typeof Blob === "undefined" ? void 0 : Blob
179
220
  );
221
+ var isFile = defineOptionalInstanceGuard(
222
+ typeof File === "undefined" ? void 0 : File
223
+ );
180
224
  var isInstanceOf = (constructor) => define((value) => value instanceof constructor);
181
225
 
182
226
  // src/core/equals.ts
@@ -197,19 +241,19 @@ function equalsBy(guard, selector) {
197
241
  }
198
242
  function equalsKey(key, target) {
199
243
  const hasMatchingKey = define((input) => {
200
- return isObject(input) && Object.hasOwn(input, key) && Object.is(input[key], target);
244
+ return isObject(input) && hasOwnPropertyKey(input, key) && Object.is(input[key], target);
201
245
  });
202
246
  return (input) => hasMatchingKey(input);
203
247
  }
204
248
 
205
249
  // src/core/key.ts
206
- var hasKey = (key) => define((input) => isObject(input) && Object.hasOwn(input, key));
250
+ var hasKey = (key) => define((input) => isObject(input) && hasOwnPropertyKey(input, key));
207
251
  var hasKeys = (...keys) => {
208
252
  if (keys.length === 0) {
209
253
  return define(() => false);
210
254
  }
211
255
  return define(
212
- (input) => isObject(input) && keys.every((key) => Object.hasOwn(input, key))
256
+ (input) => isObject(input) && hasOwnPropertyKeys(input, keys)
213
257
  );
214
258
  };
215
259
  function narrowKeyTo(guard, key) {
@@ -230,42 +274,6 @@ function lazy(factory) {
230
274
  };
231
275
  }
232
276
 
233
- // src/utils/guard-collections.ts
234
- var everyArrayValue = (values, predicate) => {
235
- for (const value of values) {
236
- if (!predicate(value)) return false;
237
- }
238
- return true;
239
- };
240
- var everyTupleValue = (values, predicates) => {
241
- if (values.length !== predicates.length) return false;
242
- for (const [index, predicate] of predicates.entries()) {
243
- if (!predicate(values[index])) return false;
244
- }
245
- return true;
246
- };
247
- var everySetValue = (values, predicate) => {
248
- for (const value of values) {
249
- if (!predicate(value)) return false;
250
- }
251
- return true;
252
- };
253
- var everyMapEntry = (values, keyPredicate, valuePredicate) => {
254
- for (const [key, value] of values) {
255
- if (!keyPredicate(key) || !valuePredicate(value)) return false;
256
- }
257
- return true;
258
- };
259
- var everyOwnEnumerableEntry = (values, keyPredicate, valuePredicate) => {
260
- for (const key of Object.keys(values)) {
261
- if (!keyPredicate(key) || !valuePredicate(values[key])) return false;
262
- }
263
- return true;
264
- };
265
-
266
- // src/utils/to-boolean-predicates.ts
267
- var toBooleanPredicates = (predicates) => predicates;
268
-
269
277
  // src/core/logic.ts
270
278
  function and(precondition, condition) {
271
279
  return define((input) => {
@@ -372,6 +380,7 @@ var isBigInt = define((value) => typeof value === "bigint");
372
380
  var isSymbol = define((value) => typeof value === "symbol");
373
381
  var isUndefined = define((value) => value === void 0);
374
382
  var isNull = define((value) => value === null);
383
+ var isNil = or(isNull, isUndefined);
375
384
  var isPrimitive = or(
376
385
  isString,
377
386
  isNumberPrimitive,
@@ -464,12 +473,14 @@ var isOptionalSchemaField = define(
464
473
  var hasRequiredKeys = (obj, entries) => (
465
474
  // WHY: Required fields must be own properties; inherited values should not
466
475
  // satisfy a schema because `struct` models object payload shape, not prototype chains.
467
- entries.every(([key, guard]) => Object.hasOwn(obj, key) && guard(obj[key]))
476
+ entries.every(([key, guard]) => hasOwnPropertyKey(obj, key) && guard(obj[key]))
468
477
  );
469
478
  var hasValidOptionalKeys = (obj, entries) => (
470
479
  // WHY: Optional keys are validated only when present. Missing keys stay valid
471
480
  // without forcing callers to encode `undefined` into the value guard.
472
- entries.every(([key, guard]) => !Object.hasOwn(obj, key) || guard(obj[key]))
481
+ entries.every(
482
+ ([key, guard]) => !hasOwnPropertyKey(obj, key) || guard(obj[key])
483
+ )
473
484
  );
474
485
  var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
475
486
  function optionalKey(guard) {
@@ -480,7 +491,7 @@ function struct(schema, options) {
480
491
  const optionalEntries = [];
481
492
  const schemaKeys = [];
482
493
  for (const key in schema) {
483
- if (!Object.hasOwn(schema, key)) continue;
494
+ if (!hasOwnPropertyKey(schema, key)) continue;
484
495
  const field = schema[key];
485
496
  schemaKeys.push(key);
486
497
  if (isOptionalSchemaField(field)) {
@@ -542,6 +553,7 @@ function tupleOf(...guards) {
542
553
  isDataView,
543
554
  isDate,
544
555
  isError,
556
+ isFile,
545
557
  isFiniteNumber,
546
558
  isFunction,
547
559
  isInfiniteNumber,
@@ -551,6 +563,7 @@ function tupleOf(...guards) {
551
563
  isMap,
552
564
  isNaN,
553
565
  isNegative,
566
+ isNil,
554
567
  isNull,
555
568
  isNumber,
556
569
  isNumberPrimitive,
package/dist/index.mjs CHANGED
@@ -10,6 +10,42 @@ function define(fn) {
10
10
  return (value) => !!fn(value);
11
11
  }
12
12
 
13
+ // src/utils/own-properties.ts
14
+ var hasOwnPropertyKey = (value, key) => Object.hasOwn(value, key);
15
+ var hasOwnPropertyKeys = (value, keys) => keys.every((key) => hasOwnPropertyKey(value, key));
16
+
17
+ // src/utils/guard-collections.ts
18
+ var everyIterableValue = (values, predicate) => {
19
+ for (const value of values) {
20
+ if (!predicate(value)) return false;
21
+ }
22
+ return true;
23
+ };
24
+ var everyKeyValueEntry = (entries, predicate) => {
25
+ for (const [key, value] of entries) {
26
+ if (!predicate(key, value)) return false;
27
+ }
28
+ return true;
29
+ };
30
+ var everyArrayValue = (values, predicate) => everyIterableValue(values, predicate);
31
+ var everyTupleValue = (values, predicates) => {
32
+ if (values.length !== predicates.length) return false;
33
+ for (let index = 0; index < predicates.length; index += 1) {
34
+ const predicate = predicates[index];
35
+ if (!predicate(values[index])) return false;
36
+ }
37
+ return true;
38
+ };
39
+ var everySetValue = (values, predicate) => everyIterableValue(values, predicate);
40
+ var everyMapEntry = (values, keyPredicate, valuePredicate) => everyKeyValueEntry(
41
+ values,
42
+ (key, value) => keyPredicate(key) && valuePredicate(value)
43
+ );
44
+ var everyOwnEnumerableEntry = (values, keyPredicate, valuePredicate) => everyIterableValue(
45
+ Object.keys(values),
46
+ (key) => keyPredicate(key) && valuePredicate(values[key])
47
+ );
48
+
13
49
  // src/utils/object-tags.ts
14
50
  var objectToString = Object.prototype.toString;
15
51
  var OBJECT_TAG_DATE = "[object Date]";
@@ -23,6 +59,9 @@ var OBJECT_TAG_DATA_VIEW = "[object DataView]";
23
59
  var OBJECT_TAG_ERROR = "[object Error]";
24
60
  var getTag = (value) => objectToString.call(value);
25
61
 
62
+ // src/utils/to-boolean-predicates.ts
63
+ var toBooleanPredicates = (predicates) => predicates;
64
+
26
65
  // src/core/object.ts
27
66
  var defineTagGuard = (tag) => define((value) => getTag(value) === tag);
28
67
  var defineOptionalInstanceGuard = (constructor) => constructor === void 0 ? define(() => false) : define(
@@ -75,6 +114,9 @@ var isURL = defineOptionalInstanceGuard(
75
114
  var isBlob = defineOptionalInstanceGuard(
76
115
  typeof Blob === "undefined" ? void 0 : Blob
77
116
  );
117
+ var isFile = defineOptionalInstanceGuard(
118
+ typeof File === "undefined" ? void 0 : File
119
+ );
78
120
  var isInstanceOf = (constructor) => define((value) => value instanceof constructor);
79
121
 
80
122
  // src/core/equals.ts
@@ -95,19 +137,19 @@ function equalsBy(guard, selector) {
95
137
  }
96
138
  function equalsKey(key, target) {
97
139
  const hasMatchingKey = define((input) => {
98
- return isObject(input) && Object.hasOwn(input, key) && Object.is(input[key], target);
140
+ return isObject(input) && hasOwnPropertyKey(input, key) && Object.is(input[key], target);
99
141
  });
100
142
  return (input) => hasMatchingKey(input);
101
143
  }
102
144
 
103
145
  // src/core/key.ts
104
- var hasKey = (key) => define((input) => isObject(input) && Object.hasOwn(input, key));
146
+ var hasKey = (key) => define((input) => isObject(input) && hasOwnPropertyKey(input, key));
105
147
  var hasKeys = (...keys) => {
106
148
  if (keys.length === 0) {
107
149
  return define(() => false);
108
150
  }
109
151
  return define(
110
- (input) => isObject(input) && keys.every((key) => Object.hasOwn(input, key))
152
+ (input) => isObject(input) && hasOwnPropertyKeys(input, keys)
111
153
  );
112
154
  };
113
155
  function narrowKeyTo(guard, key) {
@@ -128,42 +170,6 @@ function lazy(factory) {
128
170
  };
129
171
  }
130
172
 
131
- // src/utils/guard-collections.ts
132
- var everyArrayValue = (values, predicate) => {
133
- for (const value of values) {
134
- if (!predicate(value)) return false;
135
- }
136
- return true;
137
- };
138
- var everyTupleValue = (values, predicates) => {
139
- if (values.length !== predicates.length) return false;
140
- for (const [index, predicate] of predicates.entries()) {
141
- if (!predicate(values[index])) return false;
142
- }
143
- return true;
144
- };
145
- var everySetValue = (values, predicate) => {
146
- for (const value of values) {
147
- if (!predicate(value)) return false;
148
- }
149
- return true;
150
- };
151
- var everyMapEntry = (values, keyPredicate, valuePredicate) => {
152
- for (const [key, value] of values) {
153
- if (!keyPredicate(key) || !valuePredicate(value)) return false;
154
- }
155
- return true;
156
- };
157
- var everyOwnEnumerableEntry = (values, keyPredicate, valuePredicate) => {
158
- for (const key of Object.keys(values)) {
159
- if (!keyPredicate(key) || !valuePredicate(values[key])) return false;
160
- }
161
- return true;
162
- };
163
-
164
- // src/utils/to-boolean-predicates.ts
165
- var toBooleanPredicates = (predicates) => predicates;
166
-
167
173
  // src/core/logic.ts
168
174
  function and(precondition, condition) {
169
175
  return define((input) => {
@@ -270,6 +276,7 @@ var isBigInt = define((value) => typeof value === "bigint");
270
276
  var isSymbol = define((value) => typeof value === "symbol");
271
277
  var isUndefined = define((value) => value === void 0);
272
278
  var isNull = define((value) => value === null);
279
+ var isNil = or(isNull, isUndefined);
273
280
  var isPrimitive = or(
274
281
  isString,
275
282
  isNumberPrimitive,
@@ -362,12 +369,14 @@ var isOptionalSchemaField = define(
362
369
  var hasRequiredKeys = (obj, entries) => (
363
370
  // WHY: Required fields must be own properties; inherited values should not
364
371
  // satisfy a schema because `struct` models object payload shape, not prototype chains.
365
- entries.every(([key, guard]) => Object.hasOwn(obj, key) && guard(obj[key]))
372
+ entries.every(([key, guard]) => hasOwnPropertyKey(obj, key) && guard(obj[key]))
366
373
  );
367
374
  var hasValidOptionalKeys = (obj, entries) => (
368
375
  // WHY: Optional keys are validated only when present. Missing keys stay valid
369
376
  // without forcing callers to encode `undefined` into the value guard.
370
- entries.every(([key, guard]) => !Object.hasOwn(obj, key) || guard(obj[key]))
377
+ entries.every(
378
+ ([key, guard]) => !hasOwnPropertyKey(obj, key) || guard(obj[key])
379
+ )
371
380
  );
372
381
  var hasOnlyAllowedKeys = (obj, allowed) => Object.keys(obj).every((key) => allowed.has(key));
373
382
  function optionalKey(guard) {
@@ -378,7 +387,7 @@ function struct(schema, options) {
378
387
  const optionalEntries = [];
379
388
  const schemaKeys = [];
380
389
  for (const key in schema) {
381
- if (!Object.hasOwn(schema, key)) continue;
390
+ if (!hasOwnPropertyKey(schema, key)) continue;
382
391
  const field = schema[key];
383
392
  schemaKeys.push(key);
384
393
  if (isOptionalSchemaField(field)) {
@@ -439,6 +448,7 @@ export {
439
448
  isDataView,
440
449
  isDate,
441
450
  isError,
451
+ isFile,
442
452
  isFiniteNumber,
443
453
  isFunction,
444
454
  isInfiniteNumber,
@@ -448,6 +458,7 @@ export {
448
458
  isMap,
449
459
  isNaN,
450
460
  isNegative,
461
+ isNil,
451
462
  isNull,
452
463
  isNumber,
453
464
  isNumberPrimitive,
package/docs/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # is-kit docs
2
+
3
+ This directory contains the public documentation site for `is-kit`.
4
+
5
+ The site is built with Next.js and shadcn/ui. It serves the marketing pages, hand-written API guides, and the generated TypeDoc output.
6
+
7
+ ## What lives here
8
+
9
+ - `app/` - Next.js routes and page entry points
10
+ - `components/` - reusable docs-site UI and page sections
11
+ - `constants/` - site navigation and page metadata
12
+ - `lib/` - docs-specific helpers and data shaping
13
+ - `public/` - static assets and generated API output
14
+
15
+ ## Local development
16
+
17
+ From the repository root:
18
+
19
+ ```bash
20
+ pnpm --filter ./docs dev
21
+ ```
22
+
23
+ Other common commands:
24
+
25
+ ```bash
26
+ pnpm --filter ./docs build
27
+ pnpm --filter ./docs start
28
+ ```
29
+
30
+ If you use `mise`, run the same commands through `mise exec`.
31
+
32
+ ## Generated API reference
33
+
34
+ The API reference is generated from the library source with TypeDoc and written to `docs/public/api`.
35
+
36
+ From the repository root:
37
+
38
+ ```bash
39
+ pnpm typedoc
40
+ ```
41
+
42
+ After generation, the docs site serves that static output under `/api`.
43
+
44
+ ## Common editing workflow
45
+
46
+ ### Update a guide or landing page
47
+
48
+ Edit the relevant route in `app/` and the supporting components in `components/`.
49
+
50
+ ### Update navigation or docs metadata
51
+
52
+ Check the files under `constants/` and `lib/`.
53
+
54
+ ### Refresh generated API docs
55
+
56
+ Run:
57
+
58
+ ```bash
59
+ pnpm typedoc
60
+ ```
61
+
62
+ ### Add or update static assets
63
+
64
+ Place them under `public/`.
65
+
66
+ ## shadcn/ui
67
+
68
+ The docs app is already configured for shadcn/ui with the `@/*` alias.
69
+
70
+ List available components:
71
+
72
+ ```bash
73
+ pnpm --filter ./docs run shadcn:list
74
+ ```
75
+
76
+ Add a component:
77
+
78
+ ```bash
79
+ pnpm --filter ./docs run shadcn:add button
80
+ ```
81
+
82
+ If you need to reinitialize shadcn:
83
+
84
+ ```bash
85
+ pnpm --filter ./docs run shadcn:init
86
+ ```
87
+
88
+ ## Example
89
+
90
+ ```tsx
91
+ import { Button } from '@/components/ui/button';
92
+
93
+ export default function Example() {
94
+ return (
95
+ <div className='space-x-2'>
96
+ <Button>Default</Button>
97
+ <Button variant='secondary'>Secondary</Button>
98
+ </div>
99
+ );
100
+ }
101
+ ```
@@ -0,0 +1,63 @@
1
+ # is-kit Agent Rules
2
+
3
+ Copy this into a consumer repository's `AGENTS.md`, `CLAUDE.md`, or
4
+ `.agents/rules/is-kit.md` when AI agents generate or review code that uses
5
+ `is-kit`.
6
+
7
+ ## Usage Rules
8
+
9
+ - Build reusable custom guards with `define<T>(...)` instead of writing
10
+ standalone type-predicate functions by hand.
11
+ - Prefer `is-kit` combinators over hand-written boolean composition when
12
+ combining existing guards.
13
+ - Use `or(isA, isB)` instead of `(value) => isA(value) || isB(value)` when the
14
+ result should be a reusable guard.
15
+ - Use `and(baseGuard, refinement)` or `andAll(...)` instead of hand-written
16
+ `&&` checks when narrowing should be preserved.
17
+ - Use `not(guard)` for reusable negated guards.
18
+ - Use `nullable(guard)`, `optional(guard)`, or `nullish(guard)` when widening an
19
+ existing guard to accept `null` and/or `undefined`.
20
+ - Use `isNil(value)` when checking a value directly for `null | undefined`.
21
+ - Use `optionalKey(guard)` for optional object keys inside `struct`.
22
+
23
+ ## Preferred Examples
24
+
25
+ ```ts
26
+ import {
27
+ and,
28
+ define,
29
+ isNil,
30
+ isNumber,
31
+ isString,
32
+ nullish,
33
+ or,
34
+ predicateToRefine
35
+ } from 'is-kit';
36
+
37
+ const isId = or(isString, isNumber);
38
+ const isMaybeName = nullish(isString);
39
+ const isSlug = define<string>(
40
+ (value) => isString(value) && /^[a-z0-9-]+$/.test(value)
41
+ );
42
+ const isPositiveNumber = and(
43
+ isNumber,
44
+ predicateToRefine<number>((value) => value > 0)
45
+ );
46
+
47
+ declare const value: unknown;
48
+
49
+ if (isNil(value)) {
50
+ return;
51
+ }
52
+ ```
53
+
54
+ ## Avoid
55
+
56
+ ```ts
57
+ declare const value: unknown;
58
+
59
+ const isId = (value: unknown) => isString(value) || isNumber(value);
60
+ const isMaybeName = (value: unknown) => value == null || isString(value);
61
+ const isSlug = (value: unknown): value is string =>
62
+ isString(value) && /^[a-z0-9-]+$/.test(value);
63
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "is-kit",
3
- "version": "1.10.0",
3
+ "version": "1.11.1",
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",
@@ -22,6 +22,7 @@
22
22
  ],
23
23
  "files": [
24
24
  "dist",
25
+ "docs/agent-rules.md",
25
26
  "README.md",
26
27
  "LICENSE"
27
28
  ],