is-kit 1.0.5 → 1.1.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
@@ -5,7 +5,7 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <a href="(https://www.npmjs.com/package/is-kit">
8
+ <a href="https://www.npmjs.com/package/is-kit">
9
9
  <img src="https://img.shields.io/npm/v/is-kit.svg" alt="npm version">
10
10
  </a>
11
11
  <a href="https://jsr.io/@nyaomaru/is-kit">
@@ -115,7 +115,34 @@ When validating complex shapes, reach for `struct` — and friends like `arrayOf
115
115
  - **Define once**: `define<T>(fn)` turns a plain function into a type guard.
116
116
  - **Upgrade predicates**: `predicateToRefine(fn)` adds narrowing.
117
117
  - **Compose freely**: `and`, `or`, `not`, `oneOf`, `arrayOf`, `struct` …
118
- - **Stay ergonomic**: helpers like `nullable`, `optional`, `equals`, `safeParse`.
118
+ - **Stay ergonomic**: helpers like `nullable`, `optional`, `equals`, `safeParse`, `narrowKeyTo`.
119
+
120
+ ### Key Narrowing
121
+
122
+ `equalsBy` preserves the base type and does not narrow selected fields to literals.
123
+ When you need to narrow a property to a specific literal value, use `narrowKeyTo`.
124
+
125
+ ```ts
126
+ import { narrowKeyTo, or, struct } from 'is-kit';
127
+
128
+ // Base guard (e.g., via struct)
129
+ type User = { id: string; age: number; role: 'admin' | 'guest' | 'trial' };
130
+ const isUser = struct({
131
+ id: isString,
132
+ age: isNumber,
133
+ role: oneOfValues('admin', 'guest', 'trial'),
134
+ });
135
+
136
+ const byRole = narrowKeyTo(isUser, 'role');
137
+ const isGuest = byRole('guest'); // Readonly<User> & { role: 'guest' }
138
+ const isTrial = byRole('trial'); // Readonly<User> & { role: 'trial' }
139
+ const isGuestOrTrial = or(isGuest, isTrial);
140
+
141
+ declare const value: unknown;
142
+ if (isGuestOrTrial(value)) {
143
+ // value.role is 'guest' | 'trial'
144
+ }
145
+ ```
119
146
 
120
147
  ## API Reference
121
148
 
package/dist/index.d.mts CHANGED
@@ -225,7 +225,7 @@ declare const isNull: Predicate<null>;
225
225
  * @param elementGuard Guard applied to each array element.
226
226
  * @returns Predicate narrowing to a readonly array of the guarded element type.
227
227
  */
228
- declare function arrayOf<F extends (value: unknown) => value is unknown>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
228
+ declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
229
229
 
230
230
  /**
231
231
  * Validates a fixed-length tuple by applying element-wise guards.
@@ -243,8 +243,8 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
243
243
  * @param guards One or more type guards/refinements to try.
244
244
  * @returns Predicate that narrows to the union of guarded types.
245
245
  */
246
- declare function oneOf<Fs extends readonly ((value: unknown) => value is unknown)[]>(...guards: Fs): Predicate<GuardedOf<Fs[number]>>;
247
- declare function oneOf<A, Fs extends readonly ((value: A) => value is A)[]>(...guards: Fs): (input: A) => input is GuardedWithin<Fs, A>;
246
+ declare function oneOf<Fs extends readonly Predicate<unknown>[]>(...guards: Fs): Predicate<GuardedOf<Fs[number]>>;
247
+ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (input: A) => input is GuardedWithin<Fs, A>;
248
248
 
249
249
  /**
250
250
  * Validates a record-like object by guarding both keys and values.
@@ -253,7 +253,7 @@ declare function oneOf<A, Fs extends readonly ((value: A) => value is A)[]>(...g
253
253
  * @param valueFunction Guard applied to each value in the record.
254
254
  * @returns Predicate narrowing to a readonly record with guarded key/value types.
255
255
  */
256
- declare function recordOf<KF extends (value: unknown) => value is string, VF extends (value: unknown) => value is unknown>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
256
+ declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
257
257
 
258
258
  /**
259
259
  * Validates an object against a field-to-guard schema.
@@ -379,6 +379,20 @@ declare const isURL: Predicate<URL>;
379
379
  */
380
380
  declare const isBlob: Predicate<Blob>;
381
381
 
382
+ /**
383
+ * Builds a guard that narrows a specific key to the provided literal value.
384
+ *
385
+ * Given a base guard and a property key, returns a function that accepts a
386
+ * target value and produces a guard of the base type intersected with
387
+ * `{ [key]: target }`.
388
+ *
389
+ * @param guard Base guard for objects that include `key`.
390
+ * @param key Property key to narrow.
391
+ * @returns Builder that takes a literal `target` and returns a guard that
392
+ * narrows `key` to that literal.
393
+ */
394
+ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <const T extends A[K]>(target: T) => Predicate<A & Record<K, T>>;
395
+
382
396
  /**
383
397
  * Converts an array of guards to plain boolean predicates for iteration helpers.
384
398
  *
@@ -387,4 +401,4 @@ declare const isBlob: Predicate<Blob>;
387
401
  */
388
402
  declare const toBooleanPredicates: (guards: readonly Guard<unknown>[]) => ReadonlyArray<(value: unknown) => boolean>;
389
403
 
390
- 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, define, equals, equalsBy, equalsKey, guardIn, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isIterable, isMap, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
404
+ 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, define, equals, equalsBy, equalsKey, guardIn, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isIterable, isMap, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
package/dist/index.d.ts CHANGED
@@ -225,7 +225,7 @@ declare const isNull: Predicate<null>;
225
225
  * @param elementGuard Guard applied to each array element.
226
226
  * @returns Predicate narrowing to a readonly array of the guarded element type.
227
227
  */
228
- declare function arrayOf<F extends (value: unknown) => value is unknown>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
228
+ declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
229
229
 
230
230
  /**
231
231
  * Validates a fixed-length tuple by applying element-wise guards.
@@ -243,8 +243,8 @@ declare function tupleOf<const Fs extends readonly Predicate<unknown>[]>(...guar
243
243
  * @param guards One or more type guards/refinements to try.
244
244
  * @returns Predicate that narrows to the union of guarded types.
245
245
  */
246
- declare function oneOf<Fs extends readonly ((value: unknown) => value is unknown)[]>(...guards: Fs): Predicate<GuardedOf<Fs[number]>>;
247
- declare function oneOf<A, Fs extends readonly ((value: A) => value is A)[]>(...guards: Fs): (input: A) => input is GuardedWithin<Fs, A>;
246
+ declare function oneOf<Fs extends readonly Predicate<unknown>[]>(...guards: Fs): Predicate<GuardedOf<Fs[number]>>;
247
+ declare function oneOf<A, Fs extends readonly Predicate<A>[]>(...guards: Fs): (input: A) => input is GuardedWithin<Fs, A>;
248
248
 
249
249
  /**
250
250
  * Validates a record-like object by guarding both keys and values.
@@ -253,7 +253,7 @@ declare function oneOf<A, Fs extends readonly ((value: A) => value is A)[]>(...g
253
253
  * @param valueFunction Guard applied to each value in the record.
254
254
  * @returns Predicate narrowing to a readonly record with guarded key/value types.
255
255
  */
256
- declare function recordOf<KF extends (value: unknown) => value is string, VF extends (value: unknown) => value is unknown>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
256
+ declare function recordOf<KF extends Predicate<string>, VF extends Predicate<unknown>>(keyFunction: KF, valueFunction: VF): Predicate<Readonly<Record<GuardedOf<KF>, GuardedOf<VF>>>>;
257
257
 
258
258
  /**
259
259
  * Validates an object against a field-to-guard schema.
@@ -379,6 +379,20 @@ declare const isURL: Predicate<URL>;
379
379
  */
380
380
  declare const isBlob: Predicate<Blob>;
381
381
 
382
+ /**
383
+ * Builds a guard that narrows a specific key to the provided literal value.
384
+ *
385
+ * Given a base guard and a property key, returns a function that accepts a
386
+ * target value and produces a guard of the base type intersected with
387
+ * `{ [key]: target }`.
388
+ *
389
+ * @param guard Base guard for objects that include `key`.
390
+ * @param key Property key to narrow.
391
+ * @returns Builder that takes a literal `target` and returns a guard that
392
+ * narrows `key` to that literal.
393
+ */
394
+ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <const T extends A[K]>(target: T) => Predicate<A & Record<K, T>>;
395
+
382
396
  /**
383
397
  * Converts an array of guards to plain boolean predicates for iteration helpers.
384
398
  *
@@ -387,4 +401,4 @@ declare const isBlob: Predicate<Blob>;
387
401
  */
388
402
  declare const toBooleanPredicates: (guards: readonly Guard<unknown>[]) => ReadonlyArray<(value: unknown) => boolean>;
389
403
 
390
- 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, define, equals, equalsBy, equalsKey, guardIn, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isIterable, isMap, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
404
+ 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, define, equals, equalsBy, equalsKey, guardIn, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isIterable, isMap, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
package/dist/index.js CHANGED
@@ -54,6 +54,7 @@ __export(index_exports, {
54
54
  isTypedArray: () => isTypedArray,
55
55
  isURL: () => isURL,
56
56
  isUndefined: () => isUndefined,
57
+ narrowKeyTo: () => narrowKeyTo,
57
58
  nonNull: () => nonNull,
58
59
  not: () => not,
59
60
  nullable: () => nullable,
@@ -275,8 +276,8 @@ function struct(schema, options) {
275
276
  if (!isPlainObject(input)) return false;
276
277
  const obj = input;
277
278
  for (const key of Object.keys(schema)) {
278
- const guard = schema[key];
279
279
  if (!(key in obj)) return false;
280
+ const guard = schema[key];
280
281
  if (!guard(obj[key])) return false;
281
282
  }
282
283
  if (options?.exact) {
@@ -303,6 +304,16 @@ function oneOfValues(...values) {
303
304
  return valueSet.has(input);
304
305
  };
305
306
  }
307
+
308
+ // src/core/key.ts
309
+ function narrowKeyTo(guard, key) {
310
+ return function(target) {
311
+ const keyEquals = equalsKey(key, target);
312
+ return function(input) {
313
+ return guard(input) && keyEquals(input);
314
+ };
315
+ };
316
+ }
306
317
  // Annotate the CommonJS export names for ESM import in node:
307
318
  0 && (module.exports = {
308
319
  and,
@@ -339,6 +350,7 @@ function oneOfValues(...values) {
339
350
  isTypedArray,
340
351
  isURL,
341
352
  isUndefined,
353
+ narrowKeyTo,
342
354
  nonNull,
343
355
  not,
344
356
  nullable,
package/dist/index.mjs CHANGED
@@ -200,8 +200,8 @@ function struct(schema, options) {
200
200
  if (!isPlainObject(input)) return false;
201
201
  const obj = input;
202
202
  for (const key of Object.keys(schema)) {
203
- const guard = schema[key];
204
203
  if (!(key in obj)) return false;
204
+ const guard = schema[key];
205
205
  if (!guard(obj[key])) return false;
206
206
  }
207
207
  if (options?.exact) {
@@ -228,6 +228,16 @@ function oneOfValues(...values) {
228
228
  return valueSet.has(input);
229
229
  };
230
230
  }
231
+
232
+ // src/core/key.ts
233
+ function narrowKeyTo(guard, key) {
234
+ return function(target) {
235
+ const keyEquals = equalsKey(key, target);
236
+ return function(input) {
237
+ return guard(input) && keyEquals(input);
238
+ };
239
+ };
240
+ }
231
241
  export {
232
242
  and,
233
243
  andAll,
@@ -263,6 +273,7 @@ export {
263
273
  isTypedArray,
264
274
  isURL,
265
275
  isUndefined,
276
+ narrowKeyTo,
266
277
  nonNull,
267
278
  not,
268
279
  nullable,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "is-kit",
3
- "version": "1.0.5",
3
+ "version": "1.1.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",