@modulify/validator 0.2.1 → 0.3.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +12 -2
  3. package/dist/assert.cjs +99 -63
  4. package/dist/assert.d.cts +37 -0
  5. package/dist/assert.d.mts +37 -0
  6. package/dist/assert.d.ts +24 -3
  7. package/dist/assert.mjs +94 -64
  8. package/dist/assertions.cjs +283 -178
  9. package/dist/assertions.d.cts +56 -0
  10. package/dist/assertions.d.mts +56 -0
  11. package/dist/assertions.d.ts +43 -45
  12. package/dist/assertions.mjs +274 -201
  13. package/dist/checkers.cjs +23 -0
  14. package/dist/checkers.d.cts +8 -0
  15. package/dist/checkers.d.mts +8 -0
  16. package/dist/checkers.d.ts +1 -1
  17. package/dist/checkers.mjs +16 -0
  18. package/dist/combinators.cjs +305 -304
  19. package/dist/combinators.d.cts +16 -0
  20. package/dist/combinators.d.mts +16 -0
  21. package/dist/combinators.d.ts +15 -16
  22. package/dist/combinators.mjs +305 -314
  23. package/dist/constraints.cjs +23 -0
  24. package/dist/constraints.d.cts +4 -0
  25. package/dist/constraints.d.mts +4 -0
  26. package/dist/constraints.d.ts +2 -2
  27. package/dist/constraints.mjs +21 -0
  28. package/dist/extractors.cjs +6 -0
  29. package/dist/extractors.d.cts +2 -0
  30. package/dist/extractors.d.mts +2 -0
  31. package/dist/extractors.mjs +5 -0
  32. package/dist/index.cjs +140 -219
  33. package/dist/index.d.cts +12 -0
  34. package/dist/index.d.mts +12 -0
  35. package/dist/index.d.ts +9 -9
  36. package/dist/index.mjs +93 -222
  37. package/dist/json-schema.cjs +364 -489
  38. package/dist/json-schema.d.cts +14 -0
  39. package/dist/json-schema.d.mts +14 -0
  40. package/dist/json-schema.d.ts +3 -3
  41. package/dist/json-schema.mjs +365 -492
  42. package/dist/metadata.cjs +98 -7
  43. package/dist/metadata.d.cts +8 -0
  44. package/dist/metadata.d.mts +8 -0
  45. package/dist/metadata.d.ts +2 -2
  46. package/dist/metadata.mjs +93 -7
  47. package/dist/predicates.cjs +98 -41
  48. package/dist/predicates.d.cts +77 -0
  49. package/dist/predicates.d.mts +77 -0
  50. package/dist/predicates.d.ts +25 -4
  51. package/dist/predicates.mjs +92 -66
  52. package/dist/types/index.d.cts +984 -0
  53. package/dist/types/index.d.mts +984 -0
  54. package/dist/types/index.d.ts +984 -0
  55. package/dist/types/json-schema.d.cts +75 -0
  56. package/dist/types/json-schema.d.mts +75 -0
  57. package/dist/types/json-schema.d.ts +75 -0
  58. package/dist/violations.cjs +81 -0
  59. package/dist/violations.d.cts +29 -0
  60. package/dist/violations.d.mts +29 -0
  61. package/dist/violations.d.ts +1 -1
  62. package/dist/violations.mjs +80 -0
  63. package/docs/RELEASING.md +66 -0
  64. package/docs/en/00-index.md +2 -0
  65. package/docs/en/01-shape-api.md +35 -10
  66. package/docs/en/02-metadata-and-introspection.md +2 -1
  67. package/docs/en/03-violations.md +1 -1
  68. package/docs/en/04-json-schema-export.md +5 -0
  69. package/docs/en/05-public-api.md +35 -3
  70. package/docs/en/06-common-recipes.md +2 -1
  71. package/docs/en/07-ai-reference.md +5 -2
  72. package/docs/en/08-violation-code-types.md +28 -2
  73. package/docs/en/09-migration.md +75 -0
  74. package/docs/ru/00-index.md +2 -0
  75. package/docs/ru/01-shape-api.md +35 -10
  76. package/docs/ru/02-metadata-and-introspection.md +2 -1
  77. package/docs/ru/03-violations.md +1 -1
  78. package/docs/ru/04-json-schema-export.md +5 -0
  79. package/docs/ru/05-public-api.md +35 -3
  80. package/docs/ru/06-common-recipes.md +2 -1
  81. package/docs/ru/07-ai-reference.md +5 -2
  82. package/docs/ru/08-violation-code-types.md +28 -2
  83. package/docs/ru/09-migration.md +76 -0
  84. package/docs/ru/README.md +10 -2
  85. package/package.json +63 -37
  86. package/types/index.d.ts +275 -115
  87. package/dist/metadata.cjs.js +0 -130
  88. package/dist/metadata.es.js +0 -131
@@ -0,0 +1,984 @@
1
+ /** Internal utility that intersects all members of a tuple into a single type. */
2
+ export type Intersect<T extends readonly unknown[]> =
3
+ T extends readonly [infer First, ...infer Rest extends readonly unknown[]]
4
+ ? First & Intersect<Rest>
5
+ : unknown;
6
+
7
+ /** Internal utility that converts a union like `A | B` into `A & B`. */
8
+ export type UnionToIntersection<T> =
9
+ (T extends unknown ? (value: T) => void : never) extends (value: infer I) => void
10
+ ? I
11
+ : never;
12
+
13
+ /** Internal helper for nested validation results. */
14
+ export type Recursive<T> = T | Recursive<T>[]
15
+
16
+ /** Accepts either a single value or an array of values. */
17
+ export type MaybeMany<V> = V | readonly V[]
18
+ /** Accepts either a plain value or a promise of that value. */
19
+ export type MaybePromise<V> = V | Promise<V>
20
+
21
+ /** Runtime predicate that also acts as a TypeScript type guard. */
22
+ export type Predicate<T = unknown> = (value: unknown) => value is T
23
+
24
+ /** Checker used by assertion constraints after a value is extracted. */
25
+ export type Checker<T, A extends readonly unknown[] = readonly unknown[]> = (value: T, ...args: A) => boolean
26
+
27
+ /** Extracts a derived value from the original input before a checker runs. */
28
+ export type Extractor<T, V> = (value: T) => V
29
+
30
+ /** Public stage marker for assertion pipelines. */
31
+ export type AssertionStage = 'guard' | 'refinement'
32
+
33
+ /** Origin layer that produced a violation. */
34
+ export type ViolationKind = 'assertion' | 'validator' | 'runtime'
35
+
36
+ /** Contract stored in `ViolationCodeRegistry` for a known machine-readable code. */
37
+ export type ViolationCodeEntry<
38
+ K extends ViolationKind = ViolationKind,
39
+ N extends string = string,
40
+ A extends readonly unknown[] = readonly unknown[],
41
+ > = {
42
+ kind: K;
43
+ name: N;
44
+ args: A;
45
+ }
46
+
47
+ type ResolveViolationEntry<E> =
48
+ [E] extends [never]
49
+ ? ViolationCodeEntry
50
+ : E extends ViolationCodeEntry
51
+ ? E
52
+ : ViolationCodeEntry
53
+
54
+ type ResolveViolationSubjectCode<COrT extends string | readonly unknown[]> = COrT extends string ? COrT : string
55
+ type ResolveViolationSubjectArgs<COrT extends string | readonly unknown[], C extends string> = [COrT] extends [readonly unknown[]]
56
+ ? COrT
57
+ : ViolationArgs<C>
58
+
59
+ /**
60
+ * Extensible registry of machine-readable violation codes.
61
+ *
62
+ * Consumers can augment this interface in their app code:
63
+ * `declare module '@modulify/validator' { interface ViolationCodeRegistry { 'app.user.conflict': ViolationCodeEntry<'validator', 'user', readonly []> } }`
64
+ *
65
+ * Legacy `never` markers remain supported as a fallback for gradual migration:
66
+ * `declare module '@modulify/validator' { interface ViolationCodeRegistry { 'legacy.code': never } }`
67
+ */
68
+ export interface ViolationCodeRegistry {
69
+ 'date.valid': ViolationCodeEntry<'assertion', 'isValidDate', readonly []>;
70
+ 'length.exact': ViolationCodeEntry<'assertion', 'hasLength', readonly [exact: number]>;
71
+ 'length.max': ViolationCodeEntry<'assertion', 'hasLength', readonly [max: number]>;
72
+ 'length.min': ViolationCodeEntry<'assertion', 'hasLength', readonly [min: number]>;
73
+ 'length.range': ViolationCodeEntry<'assertion', 'hasLength', readonly [range: readonly [number, number]]>;
74
+ 'length.unsupported-type': ViolationCodeEntry<'assertion', 'hasLength', readonly []>;
75
+ 'number.exact': ViolationCodeEntry<'assertion', 'hasValue', readonly [exact: number]>;
76
+ 'number.finite': ViolationCodeEntry<'assertion', 'isFiniteNumber', readonly []>;
77
+ 'number.integer': ViolationCodeEntry<'assertion', 'isInteger', readonly []>;
78
+ 'number.max': ViolationCodeEntry<'assertion', 'hasValue', readonly [max: number]>;
79
+ 'number.min': ViolationCodeEntry<'assertion', 'hasValue', readonly [min: number]>;
80
+ 'number.multiple-of': ViolationCodeEntry<'assertion', 'multipleOf', readonly [step: number]>;
81
+ 'number.nan': ViolationCodeEntry<'assertion', 'isNaN', readonly []>;
82
+ 'number.range': ViolationCodeEntry<'assertion', 'hasValue', readonly [range: readonly [number, number]]>;
83
+ 'number.safe-integer': ViolationCodeEntry<'assertion', 'isSafeInteger', readonly []>;
84
+ 'number.unsupported-type': ViolationCodeEntry<'assertion', 'hasValue' | 'multipleOf', readonly []>;
85
+ 'runtime.rejection': ViolationCodeEntry<'runtime', 'validate', readonly [reason: unknown]>;
86
+ 'shape.fields.mismatch': ViolationCodeEntry<
87
+ 'validator',
88
+ 'shape',
89
+ readonly [selectors: readonly [ShapeFieldSelector, ShapeFieldSelector]]
90
+ >;
91
+ 'shape.unknown-key': ViolationCodeEntry<'validator', 'shape', readonly []>;
92
+ 'size.exact': ViolationCodeEntry<'assertion', 'hasSize', readonly [exact: number]>;
93
+ 'size.max': ViolationCodeEntry<'assertion', 'hasSize', readonly [max: number]>;
94
+ 'size.min': ViolationCodeEntry<'assertion', 'hasSize', readonly [min: number]>;
95
+ 'size.range': ViolationCodeEntry<'assertion', 'hasSize', readonly [range: readonly [number, number]]>;
96
+ 'size.unsupported-type': ViolationCodeEntry<'assertion', 'hasSize', readonly []>;
97
+ 'string.email': ViolationCodeEntry<'assertion', 'isEmail', readonly []>;
98
+ 'string.ends-with': ViolationCodeEntry<'assertion', 'endsWith', readonly [suffix: string]>;
99
+ 'string.pattern': ViolationCodeEntry<'assertion', 'hasPattern', readonly [pattern: RegExp]>;
100
+ 'string.starts-with': ViolationCodeEntry<'assertion', 'startsWith', readonly [prefix: string]>;
101
+ 'string.unsupported-type': ViolationCodeEntry<
102
+ 'assertion',
103
+ 'hasPattern' | 'startsWith' | 'endsWith',
104
+ readonly []
105
+ >;
106
+ 'tuple.length': ViolationCodeEntry<'validator', 'tuple', readonly [length: number]>;
107
+ 'type.array': ViolationCodeEntry<'validator', 'each' | 'tuple', readonly []>;
108
+ 'type.bigint': ViolationCodeEntry<'assertion', 'isBigInt', readonly []>;
109
+ 'type.blob': ViolationCodeEntry<'assertion', 'isBlob', readonly []>;
110
+ 'type.boolean': ViolationCodeEntry<'assertion', 'isBoolean', readonly []>;
111
+ 'type.date': ViolationCodeEntry<'assertion', 'isDate', readonly []>;
112
+ 'type.error': ViolationCodeEntry<'assertion', 'isError', readonly []>;
113
+ 'type.file': ViolationCodeEntry<'assertion', 'isFile', readonly []>;
114
+ 'type.function': ViolationCodeEntry<'assertion', 'isFunction', readonly []>;
115
+ 'type.map': ViolationCodeEntry<'assertion', 'isMap', readonly []>;
116
+ 'type.null': ViolationCodeEntry<'assertion', 'isNull', readonly []>;
117
+ 'type.number': ViolationCodeEntry<'assertion', 'isNumber', readonly []>;
118
+ 'type.promise-like': ViolationCodeEntry<'assertion', 'isPromiseLike', readonly []>;
119
+ 'type.record': ViolationCodeEntry<'validator', 'shape' | 'discriminatedUnion' | 'record', readonly []>;
120
+ 'type.regexp': ViolationCodeEntry<'assertion', 'isRegExp', readonly []>;
121
+ 'type.set': ViolationCodeEntry<'assertion', 'isSet', readonly []>;
122
+ 'type.string': ViolationCodeEntry<'assertion', 'isString', readonly []>;
123
+ 'type.symbol': ViolationCodeEntry<'assertion', 'isSymbol', readonly []>;
124
+ 'union.invalid-discriminator': ViolationCodeEntry<
125
+ 'validator',
126
+ 'discriminatedUnion',
127
+ readonly [variants: readonly PropertyKey[]]
128
+ >;
129
+ 'union.no-match': ViolationCodeEntry<'validator', 'union', readonly [branches: number]>;
130
+ 'value.defined': ViolationCodeEntry<'assertion', 'isDefined', readonly []>;
131
+ 'value.exact': ViolationCodeEntry<'assertion', 'exact', readonly [expected: unknown]>;
132
+ 'value.one-of': ViolationCodeEntry<'assertion', 'oneOf', readonly [values: readonly unknown[]]>;
133
+ }
134
+
135
+ /** Union of all registered machine-readable violation codes. */
136
+ export type ViolationCode = Extract<keyof ViolationCodeRegistry, string>
137
+
138
+ /** Registered codes that provide a full contract entry instead of a legacy `never` marker. */
139
+ export type KnownViolationCode = Extract<{
140
+ [C in ViolationCode]:
141
+ [ViolationCodeRegistry[C]] extends [never]
142
+ ? never
143
+ : ViolationCodeRegistry[C] extends ViolationCodeEntry
144
+ ? C
145
+ : never
146
+ }[ViolationCode], string>
147
+
148
+ /** Contract entry derived from `ViolationCodeRegistry`, with a generic fallback for unknown or legacy codes. */
149
+ export type ViolationEntry<C extends string = string> = C extends ViolationCode
150
+ ? ResolveViolationEntry<ViolationCodeRegistry[C]>
151
+ : ViolationCodeEntry
152
+
153
+ /** Tuple of machine-readable arguments associated with a violation code. */
154
+ export type ViolationArgs<C extends string = string> = ViolationEntry<C>['args']
155
+
156
+ /** Origin layer associated with a violation code. */
157
+ export type ViolationKindOf<C extends string = string> = ViolationEntry<C>['kind']
158
+
159
+ /** Constraint name associated with a violation code. */
160
+ export type ViolationNameOf<C extends string = string> = ViolationEntry<C>['name']
161
+
162
+ /** Strict code-driven violation subject for a fully registered violation code. */
163
+ export type KnownViolationSubject<C extends KnownViolationCode> = {
164
+ kind: ViolationKindOf<C>;
165
+ name: ViolationNameOf<C>;
166
+ code: C;
167
+ args: ViolationArgs<C>;
168
+ }
169
+
170
+ /** Machine-readable description of a validation failure. */
171
+ export type ViolationSubject<
172
+ COrT extends string | readonly unknown[] = string,
173
+ K extends ViolationKind = COrT extends string ? ViolationKindOf<COrT> : ViolationKind,
174
+ C extends string = ResolveViolationSubjectCode<COrT>,
175
+ T extends readonly unknown[] = ResolveViolationSubjectArgs<COrT, C>,
176
+ > = [COrT] extends [readonly unknown[]]
177
+ ? {
178
+ kind: K;
179
+ name: string;
180
+ code: C;
181
+ args: T;
182
+ }
183
+ : C extends KnownViolationCode
184
+ ? {
185
+ kind: K & ViolationKindOf<C>;
186
+ name: ViolationNameOf<C>;
187
+ code: C;
188
+ args: T & ViolationArgs<C>;
189
+ }
190
+ : {
191
+ kind: K;
192
+ name: string;
193
+ code: C;
194
+ args: T;
195
+ }
196
+
197
+ /**
198
+ * Structured validation error returned by assertions and composed validators.
199
+ *
200
+ * `path` points to the nested property or array index that failed.
201
+ *
202
+ * Example:
203
+ * `violation.violates.code === 'length.min'`
204
+ */
205
+ export type Violation<S extends ViolationSubject = ViolationSubject> = {
206
+ value: unknown;
207
+ path?: PropertyKey[];
208
+ violates: S;
209
+ }
210
+
211
+ /** Read-only utility wrapper for working with `Violation[]` results. */
212
+ export declare class ViolationCollection<V extends Violation = Violation> implements Iterable<V> {
213
+ constructor(violations: readonly V[]);
214
+ readonly size: number;
215
+ [Symbol.iterator](): Iterator<V>;
216
+ forEach(callback: (violation: V, index: number, collection: ViolationCollection<V>) => void): void;
217
+ map<T>(callback: (violation: V, index: number, collection: ViolationCollection<V>) => T): T[];
218
+ at(path: readonly PropertyKey[]): ViolationCollection<V>;
219
+ tree(): ViolationTreeNode<V>;
220
+ }
221
+
222
+ /** Tree node built from a `ViolationCollection` for nested path traversal. */
223
+ export type ViolationTreeNode<V extends Violation = Violation> = {
224
+ readonly path: readonly PropertyKey[];
225
+ readonly self: ViolationCollection<V>;
226
+ readonly subtree: ViolationCollection<V>;
227
+ readonly children: ReadonlyMap<PropertyKey, ViolationTreeNode<V>>;
228
+ at(path: readonly PropertyKey[]): ViolationTreeNode<V> | undefined;
229
+ }
230
+
231
+ /** Standard entrypoint for wrapping `Violation[]` into a collection utility API. */
232
+ export declare const collection: <V extends Violation>(violations: readonly V[]) => ViolationCollection<V>
233
+
234
+ /** Read-only machine-readable metadata attached to a constraint. */
235
+ export type ConstraintMetadata = Readonly<Record<string, unknown>>
236
+
237
+ /** Public descriptor entry for additional assertion-level checks. */
238
+ export interface AssertionConstraintDescriptor<
239
+ C extends string = string,
240
+ A extends readonly unknown[] = readonly unknown[],
241
+ > {
242
+ readonly code: C;
243
+ readonly args: A
244
+ }
245
+
246
+ /** Shared descriptor shape returned by `describe(...)`. */
247
+ export interface BaseConstraintDescriptor<K extends string = string> {
248
+ readonly kind: K;
249
+ readonly metadata?: ConstraintMetadata
250
+ }
251
+
252
+ /** Descriptor for leaf assertions created with `assert(...)` or compatible custom assertions. */
253
+ export interface AssertionDescriptor<
254
+ C extends string = string,
255
+ A extends readonly unknown[] = readonly unknown[],
256
+ T extends readonly AssertionConstraintDescriptor[] = readonly AssertionConstraintDescriptor[],
257
+ > extends BaseConstraintDescriptor<'assertion'> {
258
+ readonly name: string;
259
+ readonly bail: boolean;
260
+ readonly code: C;
261
+ readonly args: A;
262
+ readonly constraints: T
263
+ }
264
+
265
+ /** Generic fallback descriptor for custom validators without structural instrumentation. */
266
+ export type OpaqueValidatorDescriptor = BaseConstraintDescriptor<'validator'>
267
+
268
+ /** Public extension descriptor for custom validators that expose their own `describe()` contract. */
269
+ export interface CustomConstraintDescriptor<K extends string = string> extends BaseConstraintDescriptor<K> {
270
+ readonly [key: string]: unknown
271
+ }
272
+
273
+ /** Descriptor for sequential arrays of constraints used in a single slot. */
274
+ export interface AllOfConstraintDescriptor<
275
+ T extends readonly unknown[] = readonly ConstraintDescriptor[],
276
+ > extends BaseConstraintDescriptor<'allOf'> {
277
+ readonly constraints: T
278
+ }
279
+
280
+ /** Descriptor for wrapper combinators such as `optional(...)`. */
281
+ export interface WrapperConstraintDescriptor<
282
+ K extends 'optional' | 'nullable' | 'nullish' = 'optional' | 'nullable' | 'nullish',
283
+ C = ConstraintDescriptor,
284
+ > extends BaseConstraintDescriptor<K> {
285
+ readonly child: C
286
+ }
287
+
288
+ /** Descriptor for `each(...)`. */
289
+ export interface EachConstraintDescriptor<
290
+ C = ConstraintDescriptor,
291
+ > extends BaseConstraintDescriptor<'each'> {
292
+ readonly item: C
293
+ }
294
+
295
+ /** Descriptor for `tuple(...)`. */
296
+ export interface TupleConstraintDescriptor<
297
+ T extends readonly unknown[] = readonly ConstraintDescriptor[],
298
+ > extends BaseConstraintDescriptor<'tuple'> {
299
+ readonly items: T
300
+ }
301
+
302
+ /** Descriptor for `union(...)`. */
303
+ export interface UnionConstraintDescriptor<
304
+ T extends readonly unknown[] = readonly ConstraintDescriptor[],
305
+ > extends BaseConstraintDescriptor<'union'> {
306
+ readonly branches: T
307
+ }
308
+
309
+ /** Descriptor for `record(...)`. */
310
+ export interface RecordConstraintDescriptor<
311
+ C = ConstraintDescriptor,
312
+ > extends BaseConstraintDescriptor<'record'> {
313
+ readonly values: C
314
+ }
315
+
316
+ /** Descriptor for `discriminatedUnion(...)`. */
317
+ export interface DiscriminatedUnionConstraintDescriptor<
318
+ V = Readonly<Record<PropertyKey, ConstraintDescriptor>>,
319
+ > extends BaseConstraintDescriptor<'discriminatedUnion'> {
320
+ readonly key: PropertyKey;
321
+ readonly variants: V
322
+ }
323
+
324
+ /** Machine-readable summary of object-level rules registered on a shape. */
325
+ export interface ObjectShapeRuleDescriptorBase<K extends string = string> {
326
+ readonly kind: K;
327
+ readonly metadata?: ConstraintMetadata
328
+ }
329
+
330
+ /** Generic compact descriptor for sync-safe object-level rules. */
331
+ export type SyncObjectShapeRuleDescriptor<
332
+ K extends string = 'refine',
333
+ > = ObjectShapeRuleDescriptorBase<K>
334
+
335
+ /** Compact descriptor for object-level rules registered through the async-first `.refine(...)` API. */
336
+ export interface AsyncObjectShapeRuleDescriptor<
337
+ K extends string = 'refine',
338
+ > extends ObjectShapeRuleDescriptorBase<K> {
339
+ readonly async: true
340
+ }
341
+
342
+ /** Descriptor for the built-in `.fieldsMatch(...)` helper. */
343
+ export interface FieldsMatchObjectShapeRuleDescriptor<
344
+ Left extends ShapeFieldSelector = ShapeFieldSelector,
345
+ Right extends ShapeFieldSelector = ShapeFieldSelector,
346
+ > extends ObjectShapeRuleDescriptorBase<'fieldsMatch'> {
347
+ readonly selectors: readonly [Left, Right]
348
+ }
349
+
350
+ /** Machine-readable summary of object-level rules registered on a shape. */
351
+ export type ObjectShapeRuleDescriptor =
352
+ | SyncObjectShapeRuleDescriptor<string>
353
+ | AsyncObjectShapeRuleDescriptor<string>
354
+ | FieldsMatchObjectShapeRuleDescriptor
355
+
356
+ /** Descriptor for `shape(...)`. */
357
+ export interface ShapeConstraintDescriptor<
358
+ F = Readonly<Record<PropertyKey, ConstraintDescriptor>>,
359
+ R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[],
360
+ > extends BaseConstraintDescriptor<'shape'> {
361
+ readonly unknownKeys: UnknownKeysMode;
362
+ readonly fields: F;
363
+ readonly rules: R
364
+ }
365
+
366
+ /** Stable machine-readable description of a constraint tree. */
367
+ export type BuiltInConstraintDescriptor =
368
+ | AssertionDescriptor
369
+ | AllOfConstraintDescriptor
370
+ | OpaqueValidatorDescriptor
371
+ | WrapperConstraintDescriptor
372
+ | EachConstraintDescriptor
373
+ | TupleConstraintDescriptor
374
+ | UnionConstraintDescriptor
375
+ | RecordConstraintDescriptor
376
+ | DiscriminatedUnionConstraintDescriptor
377
+ | ShapeConstraintDescriptor
378
+
379
+ /** Stable machine-readable description of a constraint tree. */
380
+ export type ConstraintDescriptor = BuiltInConstraintDescriptor | CustomConstraintDescriptor
381
+
382
+ /**
383
+ * Extra checker pipeline for an assertion.
384
+ *
385
+ * Example:
386
+ * `type LengthConstraint = AssertionConstraint<string, number, [min: number], 'length.min'>`
387
+ */
388
+ export type AssertionConstraint<
389
+ // Defaults erase heterogeneous checker signatures; concrete tuples retain their types.
390
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
391
+ T = any,
392
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
393
+ V = any,
394
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
395
+ A extends readonly unknown[] = any[],
396
+ C extends string = string
397
+ > = readonly [
398
+ Extractor<T, V>,
399
+ Checker<V, A>,
400
+ C,
401
+ ...A
402
+ ]
403
+
404
+ /** Maps an assertion checker tuple into its public descriptor entry. */
405
+ export type DescribeAssertionConstraint<C extends AssertionConstraint> =
406
+ C extends readonly [unknown, unknown, infer Code extends string, ...infer A]
407
+ ? AssertionConstraintDescriptor<Code, A>
408
+ : never
409
+
410
+ /** Maps an assertion checker tuple into the violation subject it can produce. */
411
+ export type AssertionConstraintSubject<C extends AssertionConstraint, N extends string = string> =
412
+ C extends readonly [unknown, unknown, infer Code extends string, ...infer A]
413
+ ? {
414
+ kind: 'assertion';
415
+ name: N;
416
+ code: Code;
417
+ args: A;
418
+ }
419
+ : never
420
+
421
+ /** Maps assertion checker tuples into their public descriptor entries. */
422
+ export type DescribeAssertionConstraintTuple<T extends readonly AssertionConstraint[]> = {
423
+ readonly [K in keyof T]: T[K] extends AssertionConstraint
424
+ ? DescribeAssertionConstraint<T[K]>
425
+ : never
426
+ } & ReadonlyArray<DescribeAssertionConstraint<T[number]>>
427
+
428
+ declare const assertionStageBrand: unique symbol
429
+
430
+ /**
431
+ * Leaf-level validator that checks a single value and either succeeds with `null`
432
+ * or returns a structured violation.
433
+ *
434
+ * `check` is the synchronous type guard used for inference and sync narrowing.
435
+ */
436
+ export type Assertion<
437
+ T = unknown,
438
+ C extends readonly AssertionConstraint[] = readonly AssertionConstraint[],
439
+ Code extends string = string,
440
+ A extends readonly unknown[] = readonly unknown[],
441
+ Name extends string = string,
442
+ Stage extends AssertionStage = AssertionStage,
443
+ > = ((value: unknown) => MaybePromise<Omit<Violation<
444
+ Stage extends 'refinement'
445
+ ? AssertionConstraintSubject<C[number], Name>
446
+ : {
447
+ kind: 'assertion';
448
+ name: Name;
449
+ code: Code;
450
+ args: A;
451
+ } | AssertionConstraintSubject<C[number], Name>
452
+ >, 'path'> | null>) & {
453
+ readonly name: Name;
454
+ readonly bail: boolean;
455
+ readonly constraints: C;
456
+ readonly check: Predicate<T>;
457
+ readonly [assertionStageBrand]: Stage;
458
+ }
459
+
460
+ /** Assertion stage that establishes the base domain for subsequent checks. */
461
+ export type Guard<
462
+ T = unknown,
463
+ C extends readonly AssertionConstraint[] = readonly AssertionConstraint[],
464
+ Code extends string = string,
465
+ A extends readonly unknown[] = readonly unknown[],
466
+ Name extends string = string,
467
+ > = Assertion<T, C, Code, A, Name, 'guard'>
468
+
469
+ /** Assertion stage that validates properties inside an already established domain. */
470
+ export type Refinement<
471
+ T = unknown,
472
+ C extends readonly AssertionConstraint[] = readonly AssertionConstraint[],
473
+ Code extends string = string,
474
+ A extends readonly unknown[] = readonly unknown[],
475
+ Name extends string = string,
476
+ > = Assertion<T, C, Code, A, Name, 'refinement'>
477
+
478
+ /**
479
+ * Any reusable validation unit: either a leaf `Assertion` or a composed `Validator`.
480
+ *
481
+ * This is the main building block accepted by `validate(...)`, `matches.sync(...)`,
482
+ * `shape(...)`, and `each(...)`.
483
+ */
484
+ export type Constraint<T = unknown> = Assertion<T> | Validator<T>
485
+
486
+ type ConstraintSequenceState<
487
+ Value,
488
+ Ready extends boolean,
489
+ > = {
490
+ value: Value;
491
+ ready: Ready;
492
+ }
493
+
494
+ type ApplyConstraintStep<
495
+ State extends ConstraintSequenceState<unknown, boolean>,
496
+ Step extends Constraint,
497
+ > =
498
+ [Step] extends [Refinement<infer Input, readonly AssertionConstraint[], string, readonly unknown[], string>]
499
+ ? State['ready'] extends true
500
+ ? [State['value']] extends [Input]
501
+ ? ConstraintSequenceState<State['value'], true>
502
+ : never
503
+ : never
504
+ : Step extends Validator<infer Output>
505
+ ? ConstraintSequenceState<State['value'] & Output, false>
506
+ : Step extends Assertion<infer Output>
507
+ ? ConstraintSequenceState<State['value'] & Output, true>
508
+ : never
509
+
510
+ type CompatibleConstraintTupleState<
511
+ T extends readonly Constraint[],
512
+ State extends ConstraintSequenceState<unknown, boolean> = ConstraintSequenceState<unknown, false>,
513
+ > =
514
+ T extends readonly [infer First extends Constraint, ...infer Rest extends readonly Constraint[]]
515
+ ? ApplyConstraintStep<State, First> extends infer Next
516
+ ? [Next] extends [never]
517
+ ? never
518
+ : Next extends ConstraintSequenceState<unknown, boolean>
519
+ ? CompatibleConstraintTupleState<Rest, Next>
520
+ : never
521
+ : never
522
+ : State
523
+
524
+ /** Tuple of sequential constraints with stage-aware assertion compatibility checks. */
525
+ export type CompatibleConstraintTuple<T extends readonly Constraint[] = readonly Constraint[]> =
526
+ number extends T['length']
527
+ ? T
528
+ : T extends readonly [Constraint, ...Constraint[]]
529
+ ? CompatibleConstraintTupleState<T> extends never
530
+ ? never
531
+ : T
532
+ : T
533
+
534
+ /** One-or-many constraint input after applying staged assertion compatibility checks. */
535
+ export type CompatibleConstraints<C> =
536
+ C extends readonly Constraint[]
537
+ ? CompatibleConstraintTuple<C>
538
+ : C extends Refinement<unknown, readonly AssertionConstraint[], string, readonly unknown[], string>
539
+ ? never
540
+ : C extends Constraint
541
+ ? C
542
+ : never
543
+
544
+ /** Extracts the validated TypeScript type from a single constraint. */
545
+ export type InferConstraint<C> =
546
+ C extends Assertion<infer T, readonly AssertionConstraint[], string, readonly unknown[], string, AssertionStage>
547
+ ? T
548
+ : C extends Validator<infer T>
549
+ ? T
550
+ : never
551
+
552
+ type InferConstraintIntersection<C> =
553
+ (C extends unknown ? (value: InferConstraint<C>) => void : never) extends (value: infer Output) => void
554
+ ? Output
555
+ : never
556
+
557
+ /**
558
+ * Extracts the validated TypeScript type from one or many constraints.
559
+ *
560
+ * When an array of constraints is provided, their inferred types are intersected.
561
+ *
562
+ * Example:
563
+ * `InferConstraints<[typeof isDefined, typeof isString]> // string`
564
+ *
565
+ * Example:
566
+ * `InferConstraints<typeof shape({ name: [isDefined, isString] })> // { name: string }`
567
+ */
568
+ export type InferConstraints<C> =
569
+ C extends readonly []
570
+ ? unknown
571
+ : C extends readonly unknown[]
572
+ ? number extends C['length']
573
+ ? InferConstraintIntersection<C[number]>
574
+ : Intersect<{ [K in keyof C]: InferConstraint<C[K]> }>
575
+ : InferConstraint<C>
576
+
577
+ /** Internal async runner signature used by composed validators. */
578
+ export type Validate = ((
579
+ value: unknown,
580
+ constraints: CompatibleConstraints<MaybeMany<Constraint>>,
581
+ path?: PropertyKey[]
582
+ ) => Promise<Violation[]>) & {
583
+ readonly sync?: false
584
+ }
585
+
586
+ /** Internal sync runner signature used by composed validators. */
587
+ export type ValidateSync = ((
588
+ value: unknown,
589
+ constraints: CompatibleConstraints<MaybeMany<Constraint>>,
590
+ path?: PropertyKey[]
591
+ ) => Violation[]) & {
592
+ readonly sync: true
593
+ }
594
+
595
+ /** Internal union of async and sync runner signatures. */
596
+ export type ValidateLike = Validate | ValidateSync
597
+
598
+ /** Internal helper that maps a runner kind to nested validation results. */
599
+ export type Validation<F extends ValidateLike> = F extends Validate
600
+ ? MaybePromise<Violation[]>
601
+ : Violation[]
602
+
603
+ /** Controls how object shapes handle keys missing from the descriptor. */
604
+ export type UnknownKeysMode = 'passthrough' | 'strict'
605
+
606
+ /** Field selector accepted by shape helpers that can point to the current level or a nested path. */
607
+ export type ShapeFieldSelector = PropertyKey | readonly PropertyKey[]
608
+
609
+ type ResolveShapeRefinementViolationCode<COrA extends string | readonly unknown[]> = COrA extends string ? COrA : string
610
+ type ResolveShapeRefinementViolationArgs<COrA extends string | readonly unknown[], C extends string> = [COrA] extends [readonly unknown[]]
611
+ ? COrA
612
+ : ViolationArgs<C>
613
+
614
+ /** Machine-readable violation input returned by an object-level shape refinement. */
615
+ export type ShapeRefinementViolationInput<
616
+ COrA extends string | readonly unknown[] = string,
617
+ C extends string = ResolveShapeRefinementViolationCode<COrA>,
618
+ A extends readonly unknown[] = ResolveShapeRefinementViolationArgs<COrA, C>,
619
+ > = {
620
+ path?: PropertyKey[];
621
+ code: C;
622
+ args?: [COrA] extends [readonly unknown[]]
623
+ ? A
624
+ : C extends KnownViolationCode
625
+ ? A & ViolationArgs<C>
626
+ : A;
627
+ value?: unknown;
628
+ }
629
+
630
+ /** Sync-safe object-level rule that runs after the base shape has validated successfully. */
631
+ export type SyncShapeRefinement<
632
+ T,
633
+ I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput,
634
+ > = (
635
+ value: T
636
+ ) => MaybeMany<I | null | undefined> | null | undefined
637
+
638
+ /** Async-first object-level rule that runs after the base shape has validated successfully. */
639
+ export type ShapeRefinement<
640
+ T,
641
+ I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput,
642
+ > = (
643
+ value: T
644
+ ) => MaybePromise<MaybeMany<I | null | undefined> | null | undefined>
645
+
646
+ type AsyncObjectShapeRuleDescriptorOf<RD extends SyncObjectShapeRuleDescriptor<string>> =
647
+ Omit<RD, 'async'> & AsyncObjectShapeRuleDescriptor<RD['kind']>
648
+
649
+ /** Explicitly sync-safe callable helper exposed as `shape(...).refine.sync(...)`. */
650
+ export interface ShapeRefineMethodSync<
651
+ D extends ShapeDescriptor = ShapeDescriptor,
652
+ M extends UnknownKeysMode = UnknownKeysMode,
653
+ R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[],
654
+ RI extends ShapeRefinementViolationInput = never,
655
+ > {
656
+ <const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput>(
657
+ refinement: SyncShapeRefinement<InferShape<D>, I>
658
+ ): ObjectShape<D, M, [...R, SyncObjectShapeRuleDescriptor<'refine'>], RI | I>;
659
+ <
660
+ const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput,
661
+ const RD extends SyncObjectShapeRuleDescriptor<string> = SyncObjectShapeRuleDescriptor<'refine'>
662
+ >(
663
+ refinement: SyncShapeRefinement<InferShape<D>, I>,
664
+ descriptor: RD
665
+ ): ObjectShape<D, M, [...R, RD], RI | I>;
666
+ }
667
+
668
+ /** Async-first callable shape helper exposed as `shape(...).refine(...)`. */
669
+ export interface ShapeRefineMethod<
670
+ D extends ShapeDescriptor = ShapeDescriptor,
671
+ M extends UnknownKeysMode = UnknownKeysMode,
672
+ R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[],
673
+ RI extends ShapeRefinementViolationInput = never,
674
+ > {
675
+ <const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput>(
676
+ refinement: ShapeRefinement<InferShape<D>, I>
677
+ ): ObjectShape<D, M, [...R, AsyncObjectShapeRuleDescriptor<'refine'>], RI | I>;
678
+ <
679
+ const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput,
680
+ const RD extends SyncObjectShapeRuleDescriptor<string> = SyncObjectShapeRuleDescriptor<'refine'>
681
+ >(
682
+ refinement: ShapeRefinement<InferShape<D>, I>,
683
+ descriptor: RD
684
+ ): ObjectShape<D, M, [...R, AsyncObjectShapeRuleDescriptorOf<RD>], RI | I>;
685
+ sync: ShapeRefineMethodSync<D, M, R, RI>;
686
+ }
687
+
688
+ type KnownCodeViolation<C extends KnownViolationCode> = Violation<KnownViolationSubject<C>>
689
+
690
+ type ShapeRefinementIssueSubject<I extends ShapeRefinementViolationInput> =
691
+ I extends ShapeRefinementViolationInput<string | readonly unknown[], infer C, infer A>
692
+ ? C extends KnownViolationCode
693
+ ? {
694
+ kind: 'validator';
695
+ name: 'shape' & ViolationNameOf<C>;
696
+ code: C;
697
+ args: A & ViolationArgs<C>;
698
+ }
699
+ : ViolationSubject<A, 'validator', C>
700
+ : never
701
+
702
+ type ShapeRefinementIssueViolation<I extends ShapeRefinementViolationInput> =
703
+ I extends ShapeRefinementViolationInput
704
+ ? Violation<ShapeRefinementIssueSubject<I>>
705
+ : never
706
+
707
+ type InferShapeViolations<D extends ShapeDescriptor> = {
708
+ [K in keyof D]: InferViolations<D[K]>
709
+ }[keyof D]
710
+
711
+ /** Maps a single constraint into the union of violations it can produce. */
712
+ export type InferConstraintViolations<C extends Constraint> =
713
+ C extends Guard<unknown, infer AC, infer Code, infer Args, infer Name>
714
+ ? Violation<{
715
+ kind: 'assertion';
716
+ name: Name;
717
+ code: Code;
718
+ args: Args;
719
+ } | AssertionConstraintSubject<AC[number], Name>>
720
+ : C extends Refinement<unknown, infer AC, string, readonly unknown[], infer Name>
721
+ ? Violation<AssertionConstraintSubject<AC[number], Name>>
722
+ : C extends ObjectShape<infer D, infer M, readonly ObjectShapeRuleDescriptor[], infer RI>
723
+ ? KnownCodeViolation<'type.record'>
724
+ | (M extends 'strict' ? KnownCodeViolation<'shape.unknown-key'> : never)
725
+ | InferShapeViolations<D>
726
+ | ShapeRefinementIssueViolation<RI>
727
+ : C extends OptionalValidator<infer Child>
728
+ ? InferViolations<Child>
729
+ : C extends NullableValidator<infer Child>
730
+ ? InferViolations<Child>
731
+ : C extends NullishValidator<infer Child>
732
+ ? InferViolations<Child>
733
+ : C extends EachValidator<infer Child>
734
+ ? KnownCodeViolation<'type.array'> | InferViolations<Child>
735
+ : C extends TupleValidator<infer Items>
736
+ ? KnownCodeViolation<'type.array'>
737
+ | KnownCodeViolation<'tuple.length'>
738
+ | InferViolations<Items[number]>
739
+ : C extends UnionValidator<infer Branches>
740
+ ? KnownCodeViolation<'union.no-match'> | InferViolations<Branches[number]>
741
+ : C extends DiscriminatedUnionValidator<PropertyKey, infer Variants>
742
+ ? KnownCodeViolation<'type.record'>
743
+ | KnownCodeViolation<'union.invalid-discriminator'>
744
+ | InferViolations<Variants[keyof Variants]>
745
+ : C extends RecordValidator<infer Values>
746
+ ? KnownCodeViolation<'type.record'> | InferViolations<Values>
747
+ : C extends Validator
748
+ ? Violation
749
+ : never
750
+
751
+ /** Maps one-or-many constraints into the union of violations they can produce. */
752
+ export type InferViolations<C extends MaybeMany<Constraint>> =
753
+ C extends readonly []
754
+ ? never
755
+ : C extends readonly Constraint[]
756
+ ? InferConstraintViolations<C[number]>
757
+ : C extends Constraint
758
+ ? InferConstraintViolations<C>
759
+ : never
760
+
761
+ /** Successful `validate(...)` tuple with typed `validated` value. */
762
+ export type ValidationSuccess<T> = [ok: true, validated: T, violations: []]
763
+
764
+ /** Failed `validate(...)` tuple with original value and collected violations. */
765
+ export type ValidationFailure<V extends Violation = Violation> = [ok: false, validated: unknown, violations: V[]]
766
+
767
+ /**
768
+ * The result returned by `validate(...)` and `validate.sync(...)`.
769
+ *
770
+ * Example:
771
+ * `const [ok, validated, violations] = await validate(value, schema)`
772
+ *
773
+ * Example:
774
+ * `if (ok) validated.name.toUpperCase()`
775
+ */
776
+ export type ValidationResult<T, V extends Violation = Violation> = ValidationSuccess<T> | ValidationFailure<V>
777
+
778
+ /** Attaches read-only metadata to a constraint without changing validation semantics. */
779
+ export declare const meta: <const C extends Constraint, const M extends ConstraintMetadata>(constraint: C, metadata: M) => C
780
+
781
+ /**
782
+ * Composed validator used by recursive helpers such as `shape(...)` and `each(...)`.
783
+ *
784
+ * Custom validators should keep `check` aligned with runtime behavior so that
785
+ * inference and sync narrowing stay trustworthy.
786
+ *
787
+ * Example:
788
+ * `const schema: Validator<{ name: string }>`
789
+ */
790
+ export interface Validator<T = unknown> {
791
+ readonly check: Predicate<T>;
792
+ run <F extends ValidateLike> (
793
+ validate: F,
794
+ value: unknown,
795
+ path: PropertyKey[]
796
+ ): Validation<F>[];
797
+ }
798
+
799
+ /** Public validator extension contract for participating in `describe(...)` without private runtime knowledge. */
800
+ export interface DescribedValidator<
801
+ T = unknown,
802
+ D extends ConstraintDescriptor = ConstraintDescriptor,
803
+ > extends Validator<T> {
804
+ describe(): D;
805
+ }
806
+
807
+ /** Identity helper that preserves the exact shape of custom validators, including public descriptors. */
808
+ export declare const custom: <const V extends Validator>(validator: V) => V
809
+
810
+ /** Descriptor that maps object keys to one or many constraints. */
811
+ export type ShapeDescriptor = Record<PropertyKey, MaybeMany<Constraint>>
812
+
813
+ /** Shape descriptor with stage-aware compatibility checks applied to every field slot. */
814
+ export type CompatibleShapeDescriptor<D extends ShapeDescriptor> = {
815
+ [K in keyof D]: CompatibleConstraints<D[K]>
816
+ }
817
+
818
+ /** Runtime type inferred from a shape descriptor. */
819
+ export type InferShape<D extends ShapeDescriptor> = {
820
+ [K in keyof D]: InferConstraints<D[K]>
821
+ }
822
+
823
+ /** Descriptor produced by `.partial()` where every field accepts `undefined`. */
824
+ export type PartialShapeDescriptor<D extends ShapeDescriptor> = {
825
+ [K in keyof D]: Validator<InferConstraints<D[K]> | undefined>
826
+ }
827
+
828
+ /** Utility type for overriding descriptor keys from left to right. */
829
+ export type MergeShapeDescriptors<
830
+ Left extends ShapeDescriptor,
831
+ Right extends ShapeDescriptor,
832
+ > = Omit<Left, keyof Right> & Right
833
+
834
+ /**
835
+ * Object-aware validator with descriptor introspection and immutable shape helpers.
836
+ *
837
+ * Example:
838
+ * `const user = shape({ name: isString }).strict()`
839
+ */
840
+ export interface ObjectShape<
841
+ D extends ShapeDescriptor = ShapeDescriptor,
842
+ M extends UnknownKeysMode = 'passthrough',
843
+ R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[],
844
+ RI extends ShapeRefinementViolationInput = never,
845
+ > extends Validator<InferShape<D>> {
846
+ readonly descriptor: D;
847
+ readonly unknownKeys: M;
848
+ readonly refine: ShapeRefineMethod<D, M, R, RI>;
849
+ fieldsMatch<const K extends readonly [ShapeFieldSelector, ShapeFieldSelector]>(
850
+ keys: K
851
+ ): ObjectShape<D, M, [...R, FieldsMatchObjectShapeRuleDescriptor<K[0], K[1]>], RI | ShapeRefinementViolationInput<'shape.fields.mismatch'>>;
852
+ strict(): ObjectShape<D, 'strict', R, RI>;
853
+ passthrough(): ObjectShape<D, 'passthrough', R, RI>;
854
+ pick<const K extends readonly (keyof D)[]>(keys: K): ObjectShape<Pick<D, K[number]>, M, [], never>;
855
+ omit<const K extends readonly (keyof D)[]>(keys: K): ObjectShape<Omit<D, K[number]>, M, [], never>;
856
+ partial(): ObjectShape<PartialShapeDescriptor<D>, M, [], never>;
857
+ extend<const E extends ShapeDescriptor>(descriptor: E): ObjectShape<MergeShapeDescriptors<D, E>, M, [], never>;
858
+ merge<const E extends ShapeDescriptor, OM extends UnknownKeysMode, OR extends readonly ObjectShapeRuleDescriptor[]>(
859
+ shape: ObjectShape<E, OM, OR, ShapeRefinementViolationInput>
860
+ ): ObjectShape<MergeShapeDescriptors<D, E>, M, [], never>;
861
+ }
862
+
863
+ /** Helper that maps a single constraint into its public `describe(...)` result. */
864
+ export type DescribeConstraint<C extends Constraint> =
865
+ C extends Assertion<unknown, infer AC, infer Code, infer Args, string, AssertionStage>
866
+ ? AssertionDescriptor<Code, Args, DescribeAssertionConstraintTuple<AC>>
867
+ : C extends ObjectShape<infer D, infer M, infer R, ShapeRefinementViolationInput>
868
+ ? ShapeConstraintDescriptor<DescribeShapeDescriptor<D>, R> & { readonly unknownKeys: M }
869
+ : C extends OptionalValidator<infer Child>
870
+ ? WrapperConstraintDescriptor<'optional', DescribeConstraints<Child>>
871
+ : C extends NullableValidator<infer Child>
872
+ ? WrapperConstraintDescriptor<'nullable', DescribeConstraints<Child>>
873
+ : C extends NullishValidator<infer Child>
874
+ ? WrapperConstraintDescriptor<'nullish', DescribeConstraints<Child>>
875
+ : C extends EachValidator<infer Child>
876
+ ? EachConstraintDescriptor<DescribeConstraints<Child>>
877
+ : C extends TupleValidator<infer Items>
878
+ ? TupleConstraintDescriptor<DescribeConstraintTuple<Items>>
879
+ : C extends UnionValidator<infer Branches>
880
+ ? UnionConstraintDescriptor<DescribeConstraintTuple<Branches>>
881
+ : C extends DiscriminatedUnionValidator<PropertyKey, infer Variants>
882
+ ? DiscriminatedUnionConstraintDescriptor<DescribeShapeDescriptor<Variants>>
883
+ : C extends RecordValidator<infer Values>
884
+ ? RecordConstraintDescriptor<DescribeConstraints<Values>>
885
+ : C extends DescribedValidator<unknown, infer D>
886
+ ? D & { readonly metadata?: ConstraintMetadata }
887
+ : C extends Validator
888
+ ? OpaqueValidatorDescriptor
889
+ : never
890
+
891
+ /** Helper that maps a one-or-many constraint slot into its public `describe(...)` result. */
892
+ export type DescribeConstraints<C extends MaybeMany<Constraint>> =
893
+ C extends readonly [infer Only]
894
+ ? Only extends Constraint
895
+ ? DescribeConstraint<Only>
896
+ : never
897
+ : C extends readonly [Constraint, Constraint, ...Constraint[]]
898
+ ? AllOfConstraintDescriptor<DescribeConstraintTuple<C>>
899
+ : C extends readonly Constraint[]
900
+ ? DescribeConstraint<C[number]> | AllOfConstraintDescriptor
901
+ : C extends Constraint
902
+ ? DescribeConstraint<C>
903
+ : never
904
+
905
+ /** Helper that maps object descriptors into their `describe(...)` field tree. */
906
+ export type DescribeShapeDescriptor<D extends ShapeDescriptor> = {
907
+ [K in keyof D]: DescribeConstraints<D[K]>
908
+ }
909
+
910
+ /** Helper that maps tuples of constraints into tuples of descriptors. */
911
+ export type DescribeConstraintTuple<T extends readonly MaybeMany<Constraint>[]> = {
912
+ readonly [K in keyof T]: DescribeConstraints<T[K]>
913
+ } & ReadonlyArray<DescribeConstraints<T[number]>>
914
+
915
+ declare const optionalValidatorBrand: unique symbol
916
+ declare const nullableValidatorBrand: unique symbol
917
+ declare const nullishValidatorBrand: unique symbol
918
+ declare const eachValidatorBrand: unique symbol
919
+ declare const tupleValidatorBrand: unique symbol
920
+ declare const unionValidatorBrand: unique symbol
921
+ declare const discriminatedUnionValidatorBrand: unique symbol
922
+ declare const recordValidatorBrand: unique symbol
923
+
924
+ /** Typed validator returned by `optional(...)`. */
925
+ export type OptionalValidator<C extends MaybeMany<Constraint> = MaybeMany<Constraint>> =
926
+ Validator<InferConstraints<C> | undefined> & {
927
+ readonly [optionalValidatorBrand]: C
928
+ }
929
+
930
+ /** Typed validator returned by `nullable(...)`. */
931
+ export type NullableValidator<C extends MaybeMany<Constraint> = MaybeMany<Constraint>> =
932
+ Validator<InferConstraints<C> | null> & {
933
+ readonly [nullableValidatorBrand]: C
934
+ }
935
+
936
+ /** Typed validator returned by `nullish(...)`. */
937
+ export type NullishValidator<C extends MaybeMany<Constraint> = MaybeMany<Constraint>> =
938
+ Validator<InferConstraints<C> | null | undefined> & {
939
+ readonly [nullishValidatorBrand]: C
940
+ }
941
+
942
+ /** Typed validator returned by `each(...)`. */
943
+ export type EachValidator<C extends MaybeMany<Constraint> = MaybeMany<Constraint>> =
944
+ Validator<InferConstraints<C>[]> & {
945
+ readonly [eachValidatorBrand]: C
946
+ }
947
+
948
+ /** Typed validator returned by `tuple(...)`. */
949
+ export type TupleValidator<T extends readonly MaybeMany<Constraint>[] = readonly MaybeMany<Constraint>[]> =
950
+ Validator<{
951
+ -readonly [K in keyof T]: InferConstraints<T[K]>
952
+ }> & {
953
+ readonly [tupleValidatorBrand]: T
954
+ }
955
+
956
+ /** Typed validator returned by `union(...)`. */
957
+ export type UnionValidator<T extends readonly MaybeMany<Constraint>[] = readonly MaybeMany<Constraint>[]> =
958
+ Validator<{
959
+ [K in keyof T]: InferConstraints<T[K]>
960
+ }[number]> & {
961
+ readonly [unionValidatorBrand]: T
962
+ }
963
+
964
+ /** Typed validator returned by `discriminatedUnion(...)`. */
965
+ export type DiscriminatedUnionValidator<
966
+ K extends PropertyKey = PropertyKey,
967
+ T extends Record<PropertyKey, MaybeMany<Constraint>> = Record<PropertyKey, MaybeMany<Constraint>>,
968
+ > = Validator<{
969
+ [P in keyof T]: InferConstraints<T[P]>
970
+ }[keyof T]> & {
971
+ readonly [discriminatedUnionValidatorBrand]: {
972
+ readonly key: K;
973
+ readonly variants: T;
974
+ }
975
+ }
976
+
977
+ /** Typed validator returned by `record(...)`. */
978
+ export type RecordValidator<C extends MaybeMany<Constraint> = MaybeMany<Constraint>> =
979
+ Validator<Record<string, InferConstraints<C>>> & {
980
+ readonly [recordValidatorBrand]: C
981
+ }
982
+
983
+ /** Returns a stable machine-readable description of a constraint tree. */
984
+ export declare const describe: <const C extends Constraint>(constraint: C) => DescribeConstraint<C>