@oscarpalmer/jhunal 0.13.0 → 0.15.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/src/models.ts CHANGED
@@ -1,9 +1,19 @@
1
- import type {GenericCallback, PlainObject, Simplify} from '@oscarpalmer/atoms/models';
1
+ import type {Constructor, GenericCallback, PlainObject, Simplify} from '@oscarpalmer/atoms/models';
2
2
  import {ERROR_NAME} from './constants';
3
3
  import type {Schematic} from './schematic';
4
4
 
5
- export type Constructor<Instance = any> = new (...args: any[]) => Instance;
6
-
5
+ /**
6
+ * Removes duplicate types from a tuple, preserving first occurrence order
7
+ *
8
+ * @template Value - Tuple to deduplicate
9
+ * @template Seen - Accumulator for already-seen types _(internal)_
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // DeduplicateTuple<['string', 'number', 'string']>
14
+ * // => ['string', 'number']
15
+ * ```
16
+ */
7
17
  type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Value extends [
8
18
  infer Head,
9
19
  ...infer Tail,
@@ -13,6 +23,17 @@ type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Va
13
23
  : DeduplicateTuple<Tail, [...Seen, Head]>
14
24
  : Seen;
15
25
 
26
+ /**
27
+ * Recursively extracts {@link ValueName} strings from a type, unwrapping arrays and readonly arrays
28
+ *
29
+ * @template Value - Type to extract value names from
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // ExtractValueNames<'string'> => 'string'
34
+ * // ExtractValueNames<['string', 'number']> => 'string' | 'number'
35
+ * ```
36
+ */
16
37
  type ExtractValueNames<Value> = Value extends ValueName
17
38
  ? Value
18
39
  : Value extends (infer Item)[]
@@ -22,7 +43,21 @@ type ExtractValueNames<Value> = Value extends ValueName
22
43
  : never;
23
44
 
24
45
  /**
25
- * Infer the TypeScript type from a schema definition
46
+ * Infers the TypeScript type from a {@link Schema} definition
47
+ *
48
+ * @template Model - Schema to infer types from
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const userSchema = {
53
+ * name: 'string',
54
+ * age: 'number',
55
+ * address: { $required: false, $type: 'string' },
56
+ * } satisfies Schema;
57
+ *
58
+ * type User = Infer<typeof userSchema>;
59
+ * // { name: string; age: number; address?: string }
60
+ * ```
26
61
  */
27
62
  export type Infer<Model extends Schema> = Simplify<
28
63
  {
@@ -32,14 +67,31 @@ export type Infer<Model extends Schema> = Simplify<
32
67
  }
33
68
  >;
34
69
 
70
+ /**
71
+ * Extracts keys from a {@link Schema} whose entries are optional _(i.e., `$required` is `false`)_
72
+ *
73
+ * @template Model - {@link Schema} to extract optional keys from
74
+ */
35
75
  type InferOptionalKeys<Model extends Schema> = keyof {
36
76
  [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? Key : never]: never;
37
77
  };
38
78
 
79
+ /**
80
+ * Infers the TypeScript type of a {@link SchemaProperty}'s `$type` field, unwrapping arrays to infer their item type
81
+ *
82
+ * @template Value - `$type` value _(single or array)_
83
+ */
39
84
  type InferPropertyType<Value> = Value extends (infer Item)[]
40
85
  ? InferPropertyValue<Item>
41
86
  : InferPropertyValue<Value>;
42
87
 
88
+ /**
89
+ * Maps a single type definition to its TypeScript equivalent
90
+ *
91
+ * Resolves, in order: {@link Constructor} instances, {@link Schematic} models, {@link ValueName} strings, and nested {@link Schema} objects
92
+ *
93
+ * @template Value - single type definition
94
+ */
43
95
  type InferPropertyValue<Value> =
44
96
  Value extends Constructor<infer Instance>
45
97
  ? Instance
@@ -51,14 +103,31 @@ type InferPropertyValue<Value> =
51
103
  ? Infer<Value>
52
104
  : never;
53
105
 
106
+ /**
107
+ * Extracts keys from a {@link Schema} whose entries are required _(i.e., `$required` is not `false`)_
108
+ *
109
+ * @template Model - Schema to extract required keys from
110
+ */
54
111
  type InferRequiredKeys<Model extends Schema> = keyof {
55
112
  [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never;
56
113
  };
57
114
 
115
+ /**
116
+ * Infers the type for a top-level {@link Schema} entry, unwrapping arrays to infer their item type
117
+ *
118
+ * @template Value - Schema entry value _(single or array)_
119
+ */
58
120
  type InferSchemaEntry<Value> = Value extends (infer Item)[]
59
121
  ? InferSchemaEntryValue<Item>
60
122
  : InferSchemaEntryValue<Value>;
61
123
 
124
+ /**
125
+ * Resolves a single schema entry to its TypeScript type
126
+ *
127
+ * Handles, in order: {@link Constructor} instances, {@link Schematic} models, {@link SchemaProperty} objects, {@link NestedSchema} objects, {@link ValueName} strings, and plain {@link Schema} objects
128
+ *
129
+ * @template Value - single schema entry
130
+ */
62
131
  type InferSchemaEntryValue<Value> =
63
132
  Value extends Constructor<infer Instance>
64
133
  ? Instance
@@ -74,6 +143,13 @@ type InferSchemaEntryValue<Value> =
74
143
  ? Infer<Value>
75
144
  : never;
76
145
 
146
+ /**
147
+ * Determines whether a schema entry is optional
148
+ *
149
+ * Returns `true` if the entry is a {@link SchemaProperty} or {@link NestedSchema} with `$required` set to `false`; otherwise returns `false`
150
+ *
151
+ * @template Value - Schema entry to check
152
+ */
77
153
  type IsOptionalProperty<Value> = Value extends SchemaProperty
78
154
  ? Value['$required'] extends false
79
155
  ? true
@@ -84,44 +160,115 @@ type IsOptionalProperty<Value> = Value extends SchemaProperty
84
160
  : false
85
161
  : false;
86
162
 
163
+ /**
164
+ * Extracts the last member from a union type by leveraging intersection of function return types
165
+ *
166
+ * @template Value - Union type
167
+ */
87
168
  type LastOfUnion<Value> =
88
169
  UnionToIntersection<Value extends unknown ? () => Value : never> extends () => infer Item
89
170
  ? Item
90
171
  : never;
91
172
 
173
+ /**
174
+ * Maps each element of a tuple through {@link ToValueType}
175
+ *
176
+ * @template Value - Tuple of types to map
177
+ */
92
178
  type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail]
93
179
  ? [ToValueType<Head>, ...MapToValueTypes<Tail>]
94
180
  : [];
95
181
 
182
+ /**
183
+ * Maps each element of a tuple through {@link ToSchemaPropertyTypeEach}
184
+ *
185
+ * @template Value - Tuple of types to map
186
+ */
96
187
  type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail]
97
188
  ? [ToSchemaPropertyTypeEach<Head>, ...MapToSchemaPropertyTypes<Tail>]
98
189
  : [];
99
190
 
100
191
  /**
101
- * A nested schema with optional requirement flag
192
+ * A nested schema definition that may include a `$required` flag alongside arbitrary string-keyed properties
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * const address: NestedSchema = {
197
+ * $required: false,
198
+ * street: 'string',
199
+ * city: 'string',
200
+ * };
201
+ * ```
102
202
  */
103
203
  export type NestedSchema = {
204
+ /**
205
+ * Whether the nested schema is required (defaults to `true`)
206
+ */
104
207
  $required?: boolean;
105
- [key: string]: any;
106
- };
208
+ } & Schema;
107
209
 
210
+ /**
211
+ * Extracts keys from an object type that are optional
212
+ *
213
+ * @template Value - Object type to inspect
214
+ */
108
215
  type OptionalKeys<Value> = {
109
216
  [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
110
217
  }[keyof Value];
111
218
 
219
+ /**
220
+ * A generic schema allowing {@link NestedSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry} as values
221
+ */
222
+ type PlainSchema = {
223
+ [key: string]: NestedSchema | SchemaEntry | SchemaEntry[];
224
+ };
225
+
226
+ /**
227
+ * A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
228
+ *
229
+ * Each key may hold a single validator or an array of validators that receive the typed value
230
+ *
231
+ * @template Value - `$type` value(s) to derive validator keys from
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * const validators: PropertyValidators<'string'> = {
236
+ * string: (value) => value.length > 0,
237
+ * };
238
+ * ```
239
+ */
112
240
  type PropertyValidators<Value> = {
113
241
  [Key in ExtractValueNames<Value>]?:
114
242
  | ((value: Values[Key]) => boolean)
115
243
  | Array<(value: Values[Key]) => boolean>;
116
244
  };
117
245
 
246
+ /**
247
+ * Extracts keys from an object type that are required _(i.e., not optional)_
248
+ *
249
+ * @template Value - Object type to inspect
250
+ */
118
251
  type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
119
252
 
120
253
  /**
121
254
  * A schema for validating objects
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * const schema: Schema = {
259
+ * name: 'string',
260
+ * age: 'number',
261
+ * tags: ['string', 'number'],
262
+ * };
263
+ * ```
122
264
  */
123
265
  export type Schema = SchemaIndex;
124
266
 
267
+ /**
268
+ * A union of all valid types for a single schema entry
269
+ *
270
+ * Can be a {@link Constructor}, nested {@link Schema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
271
+ */
125
272
  type SchemaEntry =
126
273
  | Constructor
127
274
  | Schema
@@ -130,26 +277,63 @@ type SchemaEntry =
130
277
  | ValueName
131
278
  | ((value: unknown) => boolean);
132
279
 
280
+ /**
281
+ * Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link NestedSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
282
+ */
133
283
  interface SchemaIndex {
134
284
  [key: string]: NestedSchema | SchemaEntry | SchemaEntry[];
135
285
  }
136
286
 
137
287
  /**
138
- * A property definition with explicit type(s) and optional requirement flag
288
+ * A property definition with explicit type(s), an optional requirement flag, and optional validators
289
+ *
290
+ * @example
291
+ * ```ts
292
+ * const prop: SchemaProperty = {
293
+ * $required: false,
294
+ * $type: ['string', 'number'],
295
+ * $validators: {
296
+ * string: (v) => v.length > 0,
297
+ * number: (v) => v > 0,
298
+ * },
299
+ * };
300
+ * ```
139
301
  */
140
302
  export type SchemaProperty = {
303
+ /**
304
+ * Whether the property is required _(defaults to `true`)_
305
+ */
141
306
  $required?: boolean;
307
+ /**
308
+ * The type(s) the property value must match; a single {@link SchemaPropertyType} or an array
309
+ */
142
310
  $type: SchemaPropertyType | SchemaPropertyType[];
311
+ /**
312
+ * Optional validators keyed by {@link ValueName}, applied during validation
313
+ */
143
314
  $validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
144
315
  };
145
316
 
317
+ /**
318
+ * A union of valid types for a {@link SchemaProperty}'s `$type` field
319
+ *
320
+ * Can be a {@link Constructor}, {@link PlainSchema}, {@link Schematic}, {@link ValueName} string, or a custom validator function
321
+ */
146
322
  type SchemaPropertyType =
147
323
  | Constructor
148
- | Schema
324
+ | PlainSchema
149
325
  | Schematic<unknown>
150
326
  | ValueName
151
327
  | ((value: unknown) => boolean);
152
328
 
329
+ /**
330
+ * A custom error class for schema validation failures, with its `name` set to {@link ERROR_NAME}
331
+ *
332
+ * @example
333
+ * ```ts
334
+ * throw new SchematicError('Expected a string, received a number');
335
+ * ```
336
+ */
153
337
  export class SchematicError extends Error {
154
338
  constructor(message: string) {
155
339
  super(message);
@@ -158,44 +342,80 @@ export class SchematicError extends Error {
158
342
  }
159
343
  }
160
344
 
345
+ /**
346
+ * Converts a type into its corresponding {@link SchemaPropertyType}-representation
347
+ *
348
+ * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
349
+ *
350
+ * @template Value - type to convert
351
+ */
161
352
  type ToSchemaPropertyType<Value> = UnwrapSingle<
162
353
  DeduplicateTuple<MapToSchemaPropertyTypes<UnionToTuple<Value>>>
163
354
  >;
164
355
 
356
+ /**
357
+ * Converts a single type to its schema property equivalent
358
+ *
359
+ * {@link NestedSchema} values have `$required` stripped, plain objects become {@link TypedSchema}, and primitives go through {@link ToValueType}
360
+ *
361
+ * @template Value - type to convert
362
+ */
165
363
  type ToSchemaPropertyTypeEach<Value> = Value extends NestedSchema
166
364
  ? Omit<Value, '$required'>
167
365
  : Value extends PlainObject
168
366
  ? TypedSchema<Value>
169
367
  : ToValueType<Value>;
170
368
 
369
+ /**
370
+ * Converts a type into its corresponding {@link ValueName}-representation
371
+ *
372
+ * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
373
+ *
374
+ * @template Value - type to convert
375
+ */
171
376
  type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionToTuple<Value>>>>;
172
377
 
173
- type ToValueType<Value> = Value extends unknown[]
174
- ? 'array'
175
- : Value extends bigint
176
- ? 'bigint'
177
- : Value extends boolean
178
- ? 'boolean'
179
- : Value extends Date
180
- ? 'date'
181
- : Value extends Schematic<any>
182
- ? Value
183
- : Value extends Function
184
- ? 'function'
185
- : Value extends null
186
- ? 'null'
187
- : Value extends number
188
- ? 'number'
189
- : Value extends object
190
- ? 'object' | ((value: unknown) => value is Value)
191
- : Value extends string
192
- ? 'string'
193
- : Value extends symbol
194
- ? 'symbol'
195
- : Value extends undefined
196
- ? 'undefined'
197
- : (value: unknown) => value is Value;
378
+ /**
379
+ * Maps a type to its {@link ValueName} string equivalent
380
+ *
381
+ * Resolves {@link Schematic} types as-is, then performs a reverse-lookup against {@link Values} _(excluding `'object'`)_ to find a matching key. If no match is found, `object` types resolve to `'object'` or a type-guard function, and all other unrecognised types resolve to a type-guard function
382
+ *
383
+ * @template Value - type to map
384
+ *
385
+ * @example
386
+ * ```ts
387
+ * // ToValueType<string> => 'string'
388
+ * // ToValueType<number[]> => 'array'
389
+ * // ToValueType<Date> => 'date'
390
+ * ```
391
+ */
392
+ type ToValueType<Value> =
393
+ Value extends Schematic<any>
394
+ ? Value
395
+ : {
396
+ [Key in keyof Omit<Values, 'object'>]: Value extends Values[Key] ? Key : never;
397
+ }[keyof Omit<Values, 'object'>] extends infer Match
398
+ ? [Match] extends [never]
399
+ ? Value extends object
400
+ ? 'object' | ((value: unknown) => value is Value)
401
+ : (value: unknown) => value is Value
402
+ : Match
403
+ : never;
198
404
 
405
+ /**
406
+ * Generates all permutations of a tuple type
407
+ *
408
+ * Used by {@link UnwrapSingle} to allow schema types in any order for small tuples _(length ≤ 5)_
409
+ *
410
+ * @template Tuple - Tuple to permute
411
+ * @template Elput - Accumulator for the current permutation _(internal; name is Tuple backwards)_
412
+ *
413
+ * @example
414
+ * ```ts
415
+ * // TuplePermutations<['string', 'number']>
416
+ * // => ['string', 'number'] | ['number', 'string']
417
+ * ```
418
+ */
199
419
  type TuplePermutations<
200
420
  Tuple extends unknown[],
201
421
  Elput extends unknown[] = [],
@@ -208,6 +428,15 @@ type TuplePermutations<
208
428
  >;
209
429
  }[keyof Tuple & `${number}`];
210
430
 
431
+ /**
432
+ * Removes the element at a given index from a tuple
433
+ *
434
+ * Used internally by {@link TuplePermutations}
435
+ *
436
+ * @template Items - Tuple to remove from
437
+ * @template Item - Stringified index to remove
438
+ * @template Prefix - Accumulator for elements before the target _(internal)_
439
+ */
211
440
  type TupleRemoveAt<
212
441
  Items extends unknown[],
213
442
  Item extends string,
@@ -218,6 +447,18 @@ type TupleRemoveAt<
218
447
  : TupleRemoveAt<Tail, Item, [...Prefix, Head]>
219
448
  : Prefix;
220
449
 
450
+ /**
451
+ * A typed optional property definition generated by {@link TypedSchema} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
452
+ *
453
+ * @template Value - Property's type _(including `undefined`)_
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * // For `{ name?: string }`, the `name` key produces:
458
+ * // TypedPropertyOptional<string | undefined>
459
+ * // => { $required: false; $type: 'string'; ... }
460
+ * ```
461
+ */
221
462
  export type TypedPropertyOptional<Value> = {
222
463
  /**
223
464
  * The property is not required
@@ -233,6 +474,18 @@ export type TypedPropertyOptional<Value> = {
233
474
  $validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
234
475
  };
235
476
 
477
+ /**
478
+ * A typed required property definition generated by {@link TypedSchema} for required keys, with `$required` defaulting to `true`
479
+ *
480
+ * @template Value - Property's type
481
+ *
482
+ * @example
483
+ * ```ts
484
+ * // For `{ name: string }`, the `name` key produces:
485
+ * // TypedPropertyRequired<string>
486
+ * // => { $required?: true; $type: 'string'; ... }
487
+ * ```
488
+ */
236
489
  export type TypedPropertyRequired<Value> = {
237
490
  /**
238
491
  * The property is required _(defaults to `true`)_
@@ -249,7 +502,22 @@ export type TypedPropertyRequired<Value> = {
249
502
  };
250
503
 
251
504
  /**
252
- * Create a schema type constrained to match a TypeScript type
505
+ * Creates a schema type constrained to match a TypeScript type
506
+ *
507
+ * Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schematic}. Optional keys map to {@link TypedPropertyOptional} or, for plain objects, {@link TypedSchemaOptional}
508
+ *
509
+ * @template Model - Object type to generate a schema for
510
+ *
511
+ * @example
512
+ * ```ts
513
+ * type User = { name: string; age: number; bio?: string };
514
+ *
515
+ * const schema: TypedSchema<User> = {
516
+ * name: 'string',
517
+ * age: 'number',
518
+ * bio: { $required: false, $type: 'string' },
519
+ * };
520
+ * ```
253
521
  */
254
522
  export type TypedSchema<Model extends PlainObject> = Simplify<
255
523
  {
@@ -265,54 +533,148 @@ export type TypedSchema<Model extends PlainObject> = Simplify<
265
533
  }
266
534
  >;
267
535
 
536
+ /**
537
+ * A {@link TypedSchema} variant for optional nested objects, with `$required` fixed to `false`
538
+ *
539
+ * @template Model - Nested object type
540
+ */
268
541
  type TypedSchemaOptional<Model extends PlainObject> = {
269
542
  $required: false;
270
543
  } & TypedSchema<Model>;
271
544
 
545
+ /**
546
+ * A {@link TypedSchema} variant for required nested objects, with `$required` defaulting to `true`
547
+ *
548
+ * @template Model - Nested object type
549
+ */
272
550
  type TypedSchemaRequired<Model extends PlainObject> = {
273
551
  $required?: true;
274
552
  } & TypedSchema<Model>;
275
553
 
554
+ /**
555
+ * Converts a union type into an intersection
556
+ *
557
+ * Uses the contravariance of function parameter types to collapse a union into an intersection
558
+ *
559
+ * @template Value - Union type to convert
560
+ *
561
+ * @example
562
+ * ```ts
563
+ * // UnionToIntersection<{ a: 1 } | { b: 2 }>
564
+ * // => { a: 1 } & { b: 2 }
565
+ * ```
566
+ */
276
567
  type UnionToIntersection<Value> = (Value extends unknown ? (value: Value) => void : never) extends (
277
568
  value: infer Item,
278
569
  ) => void
279
570
  ? Item
280
571
  : never;
281
572
 
573
+ /**
574
+ * Converts a union type into an ordered tuple
575
+ *
576
+ * Repeatedly extracts the {@link LastOfUnion} member and prepends it to the accumulator
577
+ *
578
+ * @template Value - Union type to convert
579
+ * @template Items - Accumulator for the resulting tuple _(internal)_
580
+ *
581
+ * @example
582
+ * ```ts
583
+ * // UnionToTuple<'a' | 'b' | 'c'>
584
+ * // => ['a', 'b', 'c']
585
+ * ```
586
+ */
282
587
  type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends [never]
283
588
  ? Items
284
589
  : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Items]>;
285
590
 
591
+ /**
592
+ * Unwraps a single-element tuple to its inner type
593
+ *
594
+ * For tuples of length 2–5, returns all {@link TuplePermutations} to allow types in any order. Longer tuples are returned as-is
595
+ *
596
+ * @template Value - Tuple to potentially unwrap
597
+ *
598
+ * @example
599
+ * ```ts
600
+ * // UnwrapSingle<['string']> => 'string'
601
+ * // UnwrapSingle<['string', 'number']> => ['string', 'number'] | ['number', 'string']
602
+ * ```
603
+ */
286
604
  type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only]
287
605
  ? Only
288
606
  : Value['length'] extends 1 | 2 | 3 | 4 | 5
289
607
  ? TuplePermutations<Value>
290
608
  : Value;
291
609
 
610
+ /**
611
+ * The runtime representation of a parsed schema property, used internally during validation
612
+ *
613
+ * @example
614
+ * ```ts
615
+ * const parsed: ValidatedProperty = {
616
+ * key: 'age',
617
+ * required: true,
618
+ * types: ['number'],
619
+ * validators: { number: [(v) => v > 0] },
620
+ * };
621
+ * ```
622
+ */
292
623
  export type ValidatedProperty = {
624
+ /**
625
+ * The property name in the schema
626
+ */
293
627
  key: string;
628
+ /**
629
+ * Whether the property is required
630
+ */
294
631
  required: boolean;
632
+ /**
633
+ * The allowed types for this property
634
+ */
295
635
  types: ValidatedPropertyType[];
636
+ /**
637
+ * Custom validators grouped by {@link ValueName}
638
+ */
296
639
  validators: ValidatedPropertyValidators;
297
640
  };
298
641
 
642
+ /**
643
+ * A union of valid types for a {@link ValidatedProperty}'s `types` array
644
+ *
645
+ * Can be a callback _(custom validator)_, a {@link Schematic}, a nested {@link ValidatedProperty}, or a {@link ValueName} string
646
+ */
299
647
  export type ValidatedPropertyType =
300
648
  | GenericCallback
301
649
  | Schematic<unknown>
302
650
  | ValidatedProperty
303
651
  | ValueName;
304
652
 
653
+ /**
654
+ * A map of validator functions keyed by {@link ValueName}, used at runtime in {@link ValidatedProperty}
655
+ *
656
+ * Each key holds an array of validator functions that receive an `unknown` value and return a `boolean`
657
+ */
305
658
  export type ValidatedPropertyValidators = {
306
659
  [Key in ValueName]?: Array<(value: unknown) => boolean>;
307
660
  };
308
661
 
309
662
  /**
310
- * Valid type name strings
663
+ * Basic value types
311
664
  */
312
665
  export type ValueName = keyof Values;
313
666
 
314
667
  /**
315
- * Map of type names to their TypeScript/validatable equivalents
668
+ * Maps type name strings to their TypeScript equivalents
669
+ *
670
+ * Used by the type system to resolve {@link ValueName} strings into actual types
671
+ *
672
+ * @example
673
+ * ```ts
674
+ * // Values['string'] => string
675
+ * // Values['date'] => Date
676
+ * // Values['null'] => null
677
+ * ```
316
678
  */
317
679
  export type Values = {
318
680
  array: unknown[];
package/src/schematic.ts CHANGED
@@ -30,6 +30,8 @@ export class Schematic<Model> {
30
30
 
31
31
  /**
32
32
  * Does the value match the schema?
33
+ * @param value - Value to validate
34
+ * @returns `true` if the value matches the schema, otherwise `false`
33
35
  */
34
36
  is(value: unknown): value is Model {
35
37
  return validateObject(value, this.#properties);
@@ -38,11 +40,19 @@ export class Schematic<Model> {
38
40
 
39
41
  /**
40
42
  * Create a schematic from a schema
43
+ * @template Model - Schema type
44
+ * @param schema - Schema to create the schematic from
45
+ * @throws Throws {@link SchematicError} if the schema can not be converted into a schematic
46
+ * @returns A schematic for the given schema
41
47
  */
42
48
  export function schematic<Model extends Schema>(schema: Model): Schematic<Infer<Model>>;
43
49
 
44
50
  /**
45
51
  * Create a schematic from a typed schema
52
+ * @template Model - Existing type
53
+ * @param schema - Typed schema to create the schematic from
54
+ * @throws Throws {@link SchematicError} if the schema can not be converted into a schematic
55
+ * @returns A schematic for the given typed schema
46
56
  */
47
57
  export function schematic<Model extends PlainObject>(schema: TypedSchema<Model>): Schematic<Model>;
48
58