is-kit 1.5.0 → 1.6.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
@@ -69,7 +69,9 @@ import {
69
69
  and,
70
70
  or,
71
71
  not,
72
+ mapOf,
72
73
  optionalKey,
74
+ setOf,
73
75
  struct,
74
76
  oneOfValues,
75
77
  isNumber,
@@ -90,6 +92,8 @@ const isOther = not(isShortOrPositive);
90
92
 
91
93
  // Define object shapes
92
94
  const isRole = oneOfValues(['admin', 'member'] as const);
95
+ const isTags = setOf(isString);
96
+ const isScores = mapOf(isString, isNumber);
93
97
  const isUser = struct({
94
98
  id: isPositive, // number > 0
95
99
  name: isString, // string
@@ -102,6 +106,8 @@ isPositive(3); // true
102
106
  isShortOrPositive('foo'); // true
103
107
  isShortOrPositive(false); // false
104
108
  isOther('x'); // true
109
+ isTags(new Set(['new', 'vip'])); // true
110
+ isScores(new Map([['math', 98]])); // true
105
111
 
106
112
  const maybeUser: unknown = { id: 7, name: 'Rin', role: 'admin' };
107
113
  if (isUser(maybeUser)) {
@@ -118,7 +124,34 @@ Combine them as `optionalKey(optional(guard))` when both are allowed.
118
124
  Composed guards stay reusable:
119
125
  `isPositive` can be used standalone or as part of a `struct` definition.
120
126
 
121
- When validating complex shapes, reach for `struct` and friends like `arrayOf`, `recordOf`, or `oneOf`.
127
+ When validating complex shapes, reach for `struct` and collection
128
+ combinators like `arrayOf`, `setOf`, `mapOf`, `recordOf`, or `oneOf`.
129
+
130
+ ### Collection combinators
131
+
132
+ Use `arrayOf`, `setOf`, `mapOf`, and `recordOf` to validate homogeneous
133
+ collections while preserving precise readonly types.
134
+
135
+ ```ts
136
+ import {
137
+ arrayOf,
138
+ mapOf,
139
+ recordOf,
140
+ setOf,
141
+ isNumber,
142
+ isString
143
+ } from 'is-kit';
144
+
145
+ const isStringArray = arrayOf(isString);
146
+ const isStringSet = setOf(isString);
147
+ const isScoreMap = mapOf(isString, isNumber);
148
+ const isStringRecord = recordOf(isString, isString);
149
+
150
+ isStringArray(['a', 'b']); // true
151
+ isStringSet(new Set(['a', 'b'])); // true
152
+ isScoreMap(new Map([['math', 98]])); // true
153
+ isStringRecord({ a: 'x', b: 'y' }); // true
154
+ ```
122
155
 
123
156
  ### Primitive guards
124
157
 
@@ -165,6 +198,8 @@ isInfiniteNumber(1); // false
165
198
 
166
199
  Object/built-in guards cover arrays, dates, maps/sets, and more. Use
167
200
  `isInstanceOf` when you want a reusable guard from a class constructor.
201
+ For content-aware map/set validation, pair `isMap` / `isSet` with `mapOf`
202
+ and `setOf`.
168
203
 
169
204
  ```ts
170
205
  import { isArray, isDate, isInstanceOf } from 'is-kit';
@@ -184,7 +219,7 @@ isAnimal({}); // false
184
219
 
185
220
  - **Define once**: `define<T>(fn)` turns a plain function into a type guard.
186
221
  - **Upgrade predicates**: `predicateToRefine(fn)` adds narrowing.
187
- - **Compose freely**: `and`, `or`, `not`, `oneOf`, `arrayOf`, `struct` …
222
+ - **Compose freely**: `and`, `or`, `not`, `oneOf`, `arrayOf`, `setOf`, `mapOf`, `struct` …
188
223
  - **Stay ergonomic**: helpers like `nullable`, `optional`, `equals`, `safeParse`, `assert`, `hasKey`, `hasKeys`, `narrowKeyTo`.
189
224
 
190
225
  ### Key Helpers
package/dist/index.d.mts CHANGED
@@ -325,6 +325,23 @@ declare const isPrimitive: Guard<string | number | bigint | boolean | symbol | n
325
325
  */
326
326
  declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
327
327
 
328
+ /**
329
+ * Validates a set where every value satisfies the provided guard.
330
+ *
331
+ * @param valueGuard Guard applied to each set value.
332
+ * @returns Predicate narrowing to a readonly set of the guarded value type.
333
+ */
334
+ declare function setOf<VF extends Predicate<unknown>>(valueGuard: VF): Predicate<ReadonlySet<GuardedOf<VF>>>;
335
+
336
+ /**
337
+ * Validates a map where every key and value satisfies the provided guards.
338
+ *
339
+ * @param keyGuard Guard applied to each map key.
340
+ * @param valueGuard Guard applied to each map value.
341
+ * @returns Predicate narrowing to a readonly map with guarded key/value types.
342
+ */
343
+ declare function mapOf<KF extends Predicate<unknown>, VF extends Predicate<unknown>>(keyGuard: KF, valueGuard: VF): Predicate<ReadonlyMap<GuardedOf<KF>, GuardedOf<VF>>>;
344
+
328
345
  /**
329
346
  * Validates a fixed-length tuple by applying element-wise guards.
330
347
  *
@@ -546,4 +563,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
546
563
  */
547
564
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
548
565
 
549
- export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
566
+ export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, mapOf, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
package/dist/index.d.ts CHANGED
@@ -325,6 +325,23 @@ declare const isPrimitive: Guard<string | number | bigint | boolean | symbol | n
325
325
  */
326
326
  declare function arrayOf<F extends Predicate<unknown>>(elementGuard: F): Predicate<readonly GuardedOf<F>[]>;
327
327
 
328
+ /**
329
+ * Validates a set where every value satisfies the provided guard.
330
+ *
331
+ * @param valueGuard Guard applied to each set value.
332
+ * @returns Predicate narrowing to a readonly set of the guarded value type.
333
+ */
334
+ declare function setOf<VF extends Predicate<unknown>>(valueGuard: VF): Predicate<ReadonlySet<GuardedOf<VF>>>;
335
+
336
+ /**
337
+ * Validates a map where every key and value satisfies the provided guards.
338
+ *
339
+ * @param keyGuard Guard applied to each map key.
340
+ * @param valueGuard Guard applied to each map value.
341
+ * @returns Predicate narrowing to a readonly map with guarded key/value types.
342
+ */
343
+ declare function mapOf<KF extends Predicate<unknown>, VF extends Predicate<unknown>>(keyGuard: KF, valueGuard: VF): Predicate<ReadonlyMap<GuardedOf<KF>, GuardedOf<VF>>>;
344
+
328
345
  /**
329
346
  * Validates a fixed-length tuple by applying element-wise guards.
330
347
  *
@@ -546,4 +563,4 @@ declare function narrowKeyTo<A, K extends keyof A>(guard: Guard<A>, key: K): <co
546
563
  */
547
564
  declare const toBooleanPredicates: <A>(predicates: readonly ((value: A) => boolean)[]) => ReadonlyArray<(value: A) => boolean>;
548
565
 
549
- export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, struct, toBooleanPredicates, tupleOf };
566
+ export { type ChainResult, type Guard, type GuardedOf, type GuardedWithin, type InferSchema, type OptionalSchemaField, type OutOfGuards, type ParseResult, type Predicate, type Primitive, type Refine, type RefineChain, type Refinement, type Schema, type SchemaField, and, andAll, arrayOf, assert, define, equals, equalsBy, equalsKey, guardIn, hasKey, hasKeys, isArray, isArrayBuffer, isAsyncIterable, isBigInt, isBlob, isBoolean, isDataView, isDate, isError, isFiniteNumber, isFunction, isInfiniteNumber, isInstanceOf, isInteger, isIterable, isMap, isNaN, isNegative, isNull, isNumber, isNumberPrimitive, isObject, isPlainObject, isPositive, isPrimitive, isPromiseLike, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isURL, isUndefined, isWeakMap, isWeakSet, isZero, mapOf, narrowKeyTo, nonNull, not, nullable, nullish, oneOf, oneOfValues, optional, optionalKey, or, predicateToRefine, recordOf, required, safeParse, safeParseWith, setOf, struct, toBooleanPredicates, tupleOf };
package/dist/index.js CHANGED
@@ -68,6 +68,7 @@ __export(index_exports, {
68
68
  isWeakMap: () => isWeakMap,
69
69
  isWeakSet: () => isWeakSet,
70
70
  isZero: () => isZero,
71
+ mapOf: () => mapOf,
71
72
  narrowKeyTo: () => narrowKeyTo,
72
73
  nonNull: () => nonNull,
73
74
  not: () => not,
@@ -83,6 +84,7 @@ __export(index_exports, {
83
84
  required: () => required,
84
85
  safeParse: () => safeParse,
85
86
  safeParseWith: () => safeParseWith,
87
+ setOf: () => setOf,
86
88
  struct: () => struct,
87
89
  toBooleanPredicates: () => toBooleanPredicates,
88
90
  tupleOf: () => tupleOf
@@ -109,24 +111,24 @@ var toBooleanPredicates = (predicates) => predicates;
109
111
 
110
112
  // src/core/logic.ts
111
113
  function and(precondition, condition) {
112
- return (input) => {
114
+ return define((input) => {
113
115
  if (precondition(input)) {
114
116
  return condition(input);
115
117
  }
116
118
  return false;
117
- };
119
+ });
118
120
  }
119
121
  function andAll(precondition, ...steps) {
120
- return (input) => {
122
+ return define((input) => {
121
123
  if (!precondition(input)) return false;
122
124
  return applyRefinements(input, steps);
123
- };
125
+ });
124
126
  }
125
127
  function or(...guards) {
126
128
  const predicates = toBooleanPredicates(guards);
127
- return (input) => {
128
- return predicates.some((guard) => guard(input));
129
- };
129
+ return define(
130
+ (input) => predicates.some((guard) => guard(input))
131
+ );
130
132
  }
131
133
  function guardIn() {
132
134
  return (guard) => (input) => guard(input);
@@ -294,22 +296,45 @@ var isPrimitive = or(
294
296
 
295
297
  // src/core/combinators/array.ts
296
298
  function arrayOf(elementGuard) {
297
- return (input) => {
299
+ return define((input) => {
298
300
  if (!Array.isArray(input)) return false;
299
301
  for (const element of input) {
300
302
  if (!elementGuard(element)) return false;
301
303
  }
302
304
  return true;
303
- };
305
+ });
306
+ }
307
+
308
+ // src/core/combinators/set.ts
309
+ function setOf(valueGuard) {
310
+ return define((input) => {
311
+ if (!isSet(input)) return false;
312
+ for (const value of input.values()) {
313
+ if (!valueGuard(value)) return false;
314
+ }
315
+ return true;
316
+ });
317
+ }
318
+
319
+ // src/core/combinators/map.ts
320
+ function mapOf(keyGuard, valueGuard) {
321
+ return define((input) => {
322
+ if (!isMap(input)) return false;
323
+ for (const [key, value] of input.entries()) {
324
+ if (!keyGuard(key)) return false;
325
+ if (!valueGuard(value)) return false;
326
+ }
327
+ return true;
328
+ });
304
329
  }
305
330
 
306
331
  // src/core/combinators/tuple.ts
307
332
  function tupleOf(...guards) {
308
- return (input) => {
333
+ return define((input) => {
309
334
  return Array.isArray(input) && input.length === guards.length && guards.every(
310
335
  (guard, index) => guard(input[index])
311
336
  );
312
- };
337
+ });
313
338
  }
314
339
 
315
340
  // src/core/combinators/one-of.ts
@@ -366,14 +391,14 @@ function struct(schema, options) {
366
391
  requiredEntries.push([key, field]);
367
392
  }
368
393
  const allowed = options?.exact ? new Set(schemaKeys) : null;
369
- return (input) => {
394
+ return define((input) => {
370
395
  if (!isPlainObject(input)) return false;
371
396
  const obj = input;
372
397
  if (!hasRequiredKeys(obj, requiredEntries)) return false;
373
398
  if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
374
399
  if (!allowed) return true;
375
400
  return hasOnlyAllowedKeys(obj, allowed);
376
- };
401
+ });
377
402
  }
378
403
 
379
404
  // src/core/combinators/one-of-values.ts
@@ -387,9 +412,9 @@ var isZeroNumber = and(
387
412
  );
388
413
  var normalizeValues = (args) => isSingleArrayArg(args) ? args[0] : args;
389
414
  var createLinearPredicate = (items) => {
390
- return (input) => {
415
+ return define((input) => {
391
416
  return items.some((value) => Object.is(value, input));
392
- };
417
+ });
393
418
  };
394
419
  var createSetPredicate = (items) => {
395
420
  let hasPositiveZero = false;
@@ -403,12 +428,12 @@ var createSetPredicate = (items) => {
403
428
  valueSet.add(literalValue);
404
429
  }
405
430
  }
406
- return (input) => {
431
+ return define((input) => {
407
432
  if (isZeroNumber(input)) {
408
433
  return Object.is(input, -0) ? hasNegativeZero : hasPositiveZero;
409
434
  }
410
435
  return valueSet.has(input);
411
- };
436
+ });
412
437
  };
413
438
  function oneOfValues(...args) {
414
439
  const items = normalizeValues(args);
@@ -485,6 +510,7 @@ function narrowKeyTo(guard, key) {
485
510
  isWeakMap,
486
511
  isWeakSet,
487
512
  isZero,
513
+ mapOf,
488
514
  narrowKeyTo,
489
515
  nonNull,
490
516
  not,
@@ -500,6 +526,7 @@ function narrowKeyTo(guard, key) {
500
526
  required,
501
527
  safeParse,
502
528
  safeParseWith,
529
+ setOf,
503
530
  struct,
504
531
  toBooleanPredicates,
505
532
  tupleOf
package/dist/index.mjs CHANGED
@@ -18,24 +18,24 @@ var toBooleanPredicates = (predicates) => predicates;
18
18
 
19
19
  // src/core/logic.ts
20
20
  function and(precondition, condition) {
21
- return (input) => {
21
+ return define((input) => {
22
22
  if (precondition(input)) {
23
23
  return condition(input);
24
24
  }
25
25
  return false;
26
- };
26
+ });
27
27
  }
28
28
  function andAll(precondition, ...steps) {
29
- return (input) => {
29
+ return define((input) => {
30
30
  if (!precondition(input)) return false;
31
31
  return applyRefinements(input, steps);
32
- };
32
+ });
33
33
  }
34
34
  function or(...guards) {
35
35
  const predicates = toBooleanPredicates(guards);
36
- return (input) => {
37
- return predicates.some((guard) => guard(input));
38
- };
36
+ return define(
37
+ (input) => predicates.some((guard) => guard(input))
38
+ );
39
39
  }
40
40
  function guardIn() {
41
41
  return (guard) => (input) => guard(input);
@@ -203,22 +203,45 @@ var isPrimitive = or(
203
203
 
204
204
  // src/core/combinators/array.ts
205
205
  function arrayOf(elementGuard) {
206
- return (input) => {
206
+ return define((input) => {
207
207
  if (!Array.isArray(input)) return false;
208
208
  for (const element of input) {
209
209
  if (!elementGuard(element)) return false;
210
210
  }
211
211
  return true;
212
- };
212
+ });
213
+ }
214
+
215
+ // src/core/combinators/set.ts
216
+ function setOf(valueGuard) {
217
+ return define((input) => {
218
+ if (!isSet(input)) return false;
219
+ for (const value of input.values()) {
220
+ if (!valueGuard(value)) return false;
221
+ }
222
+ return true;
223
+ });
224
+ }
225
+
226
+ // src/core/combinators/map.ts
227
+ function mapOf(keyGuard, valueGuard) {
228
+ return define((input) => {
229
+ if (!isMap(input)) return false;
230
+ for (const [key, value] of input.entries()) {
231
+ if (!keyGuard(key)) return false;
232
+ if (!valueGuard(value)) return false;
233
+ }
234
+ return true;
235
+ });
213
236
  }
214
237
 
215
238
  // src/core/combinators/tuple.ts
216
239
  function tupleOf(...guards) {
217
- return (input) => {
240
+ return define((input) => {
218
241
  return Array.isArray(input) && input.length === guards.length && guards.every(
219
242
  (guard, index) => guard(input[index])
220
243
  );
221
- };
244
+ });
222
245
  }
223
246
 
224
247
  // src/core/combinators/one-of.ts
@@ -275,14 +298,14 @@ function struct(schema, options) {
275
298
  requiredEntries.push([key, field]);
276
299
  }
277
300
  const allowed = options?.exact ? new Set(schemaKeys) : null;
278
- return (input) => {
301
+ return define((input) => {
279
302
  if (!isPlainObject(input)) return false;
280
303
  const obj = input;
281
304
  if (!hasRequiredKeys(obj, requiredEntries)) return false;
282
305
  if (!hasValidOptionalKeys(obj, optionalEntries)) return false;
283
306
  if (!allowed) return true;
284
307
  return hasOnlyAllowedKeys(obj, allowed);
285
- };
308
+ });
286
309
  }
287
310
 
288
311
  // src/core/combinators/one-of-values.ts
@@ -296,9 +319,9 @@ var isZeroNumber = and(
296
319
  );
297
320
  var normalizeValues = (args) => isSingleArrayArg(args) ? args[0] : args;
298
321
  var createLinearPredicate = (items) => {
299
- return (input) => {
322
+ return define((input) => {
300
323
  return items.some((value) => Object.is(value, input));
301
- };
324
+ });
302
325
  };
303
326
  var createSetPredicate = (items) => {
304
327
  let hasPositiveZero = false;
@@ -312,12 +335,12 @@ var createSetPredicate = (items) => {
312
335
  valueSet.add(literalValue);
313
336
  }
314
337
  }
315
- return (input) => {
338
+ return define((input) => {
316
339
  if (isZeroNumber(input)) {
317
340
  return Object.is(input, -0) ? hasNegativeZero : hasPositiveZero;
318
341
  }
319
342
  return valueSet.has(input);
320
- };
343
+ });
321
344
  };
322
345
  function oneOfValues(...args) {
323
346
  const items = normalizeValues(args);
@@ -393,6 +416,7 @@ export {
393
416
  isWeakMap,
394
417
  isWeakSet,
395
418
  isZero,
419
+ mapOf,
396
420
  narrowKeyTo,
397
421
  nonNull,
398
422
  not,
@@ -408,6 +432,7 @@ export {
408
432
  required,
409
433
  safeParse,
410
434
  safeParseWith,
435
+ setOf,
411
436
  struct,
412
437
  toBooleanPredicates,
413
438
  tupleOf
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "is-kit",
3
- "version": "1.5.0",
3
+ "version": "1.6.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",