@zod-utils/core 1.1.0 → 2.0.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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as z from 'zod';
2
- import { util, z as z$1 } from 'zod';
2
+ import { z as z$1, util } from 'zod';
3
3
  import { $InferUnionInput, $ZodCheckLessThanDef, $ZodCheckGreaterThanDef, $ZodCheckMultipleOfDef, $ZodCheckNumberFormatDef, $ZodCheckBigIntFormatDef, $ZodCheckMaxSizeDef, $ZodCheckMinSizeDef, $ZodCheckSizeEqualsDef, $ZodCheckMaxLengthDef, $ZodCheckMinLengthDef, $ZodCheckLengthEqualsDef, $ZodCheckStringFormatDef, $ZodCheckRegexDef, $ZodCheckLowerCaseDef, $ZodCheckUpperCaseDef, $ZodCheckIncludesDef, $ZodCheckStartsWithDef, $ZodCheckEndsWithDef, $ZodCheckPropertyDef, $ZodCheckMimeTypeDef, $ZodCheckOverwriteDef } from 'zod/v4/core';
4
4
 
5
5
  /**
@@ -45,6 +45,95 @@ import { $InferUnionInput, $ZodCheckLessThanDef, $ZodCheckGreaterThanDef, $ZodCh
45
45
  type Simplify<T> = {
46
46
  [K in keyof T]: T[K];
47
47
  } & {};
48
+ /**
49
+ * Extracts all field keys from a Zod schema's input type.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const schema = z.object({ name: z.string(), age: z.number() });
54
+ * type Keys = DiscriminatorKey<typeof schema>;
55
+ * // "name" | "age"
56
+ * ```
57
+ */
58
+ type DiscriminatorKey<TSchema extends z$1.ZodType> = keyof z$1.input<TSchema> & string;
59
+ /**
60
+ * Extracts the value type for a discriminator field.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const schema = z.discriminatedUnion('mode', [
65
+ * z.object({ mode: z.literal('create'), name: z.string() }),
66
+ * z.object({ mode: z.literal('edit'), id: z.number() }),
67
+ * ]);
68
+ * type Mode = DiscriminatorValue<typeof schema, 'mode'>;
69
+ * // "create" | "edit"
70
+ * ```
71
+ */
72
+ type DiscriminatorValue<TSchema extends z$1.ZodType, TDiscriminatorKey extends DiscriminatorKey<TSchema>> = TDiscriminatorKey extends string ? z$1.input<TSchema>[TDiscriminatorKey] & util.Literal : never;
73
+ /**
74
+ * Discriminator configuration for discriminated union schemas.
75
+ */
76
+ type Discriminator<TSchema extends z$1.ZodType, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends DiscriminatorValue<TSchema, TDiscriminatorKey>> = {
77
+ key: TDiscriminatorKey;
78
+ value: TDiscriminatorValue;
79
+ };
80
+ type Primitive = string | number | boolean | null | undefined | symbol | bigint;
81
+ type NonZeroDigit = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
82
+ type PathsHint<T, Prefix extends string = ''> = T extends Primitive ? never : T extends (infer E)[] ? (Prefix extends '' ? never : Prefix) | `${Prefix}.0` | PathsHint<E, `${Prefix}.0`> : T extends object ? {
83
+ [K in keyof T & string]: (Prefix extends '' ? K : `${Prefix}.${K}`) | PathsHint<T[K], Prefix extends '' ? K : `${Prefix}.${K}`>;
84
+ }[keyof T & string] : never;
85
+ type NonZeroIndex = `${NonZeroDigit}` | `${NonZeroDigit}${number}`;
86
+ type PathsLoose<T, Prefix extends string = ''> = T extends Primitive ? never : T extends (infer E)[] ? (Prefix extends '' ? never : Prefix) | `${Prefix}.${NonZeroIndex}` | PathsLoose<E, `${Prefix}.${NonZeroIndex}`> : T extends object ? {
87
+ [K in keyof T & string]: (Prefix extends '' ? K : `${Prefix}.${K}`) | PathsLoose<T[K], Prefix extends '' ? K : `${Prefix}.${K}`>;
88
+ }[keyof T & string] : never;
89
+ /**
90
+ * Generates all valid dot-notation paths for a given type.
91
+ * Supports nested objects and arrays with numeric indices.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * type User = { name: string; address: { city: string } };
96
+ * type UserPaths = Paths<User>;
97
+ * // "name" | "address" | "address.city"
98
+ * ```
99
+ */
100
+ type Paths<T> = PathsHint<T> | PathsLoose<T>;
101
+ /**
102
+ * Extracts fields common to all variants in a union type.
103
+ *
104
+ * Uses `Pick<T, keyof T>` to normalize union types by extracting only
105
+ * the keys that exist across all union members.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * type A = { mode: 'create'; name: string };
110
+ * type B = { mode: 'edit'; id: number };
111
+ * type Common = CommonFields<A | B>;
112
+ * // { mode: 'create' | 'edit' }
113
+ * ```
114
+ */
115
+ type CommonFields<T> = Pick<T, keyof T>;
116
+ /**
117
+ * Generates valid dot-notation paths for fields in a discriminated union variant.
118
+ *
119
+ * Given a schema and discriminator value, extracts all possible field paths
120
+ * (including nested paths) for that specific variant.
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const schema = z.discriminatedUnion('mode', [
125
+ * z.object({ mode: z.literal('create'), name: z.string() }),
126
+ * z.object({ mode: z.literal('edit'), id: z.number() }),
127
+ * ]);
128
+ *
129
+ * type CreatePaths = ValidPaths<typeof schema, 'mode', 'create'>;
130
+ * // "mode" | "name"
131
+ *
132
+ * type EditPaths = ValidPaths<typeof schema, 'mode', 'edit'>;
133
+ * // "mode" | "id"
134
+ * ```
135
+ */
136
+ type ValidPaths<TSchema extends z$1.ZodType, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends DiscriminatorValue<TSchema, TDiscriminatorKey>> = Paths<CommonFields<Extract<Required<z$1.input<TSchema>>, TDiscriminatorKey extends never ? z$1.input<TSchema> : TDiscriminatorValue extends never ? z$1.input<TSchema> : Simplify<Record<TDiscriminatorKey, TDiscriminatorValue>>>>>;
48
137
 
49
138
  /**
50
139
  * Extracts the default value from a Zod field, recursively unwrapping optional, nullable, and union layers.
@@ -177,27 +266,210 @@ declare function extractDefaultValue<T extends z.ZodType>(field: T): z.input<T>
177
266
  * @see {@link extractDefaultValue} for extracting defaults from individual fields
178
267
  * @since 0.1.0
179
268
  */
180
- declare function getSchemaDefaults<TSchema extends z.ZodType, TDiscriminatorKey extends keyof z.input<TSchema> & string, TDiscriminatorValue extends z.input<TSchema>[TDiscriminatorKey] & util.Literal>(schema: TSchema, options?: {
181
- discriminator?: {
182
- key: TDiscriminatorKey;
183
- value: TDiscriminatorValue;
184
- };
269
+ declare function getSchemaDefaults<TSchema extends z.ZodType, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends DiscriminatorValue<TSchema, TDiscriminatorKey>>(schema: TSchema, options?: {
270
+ discriminator?: Discriminator<TSchema, TDiscriminatorKey, TDiscriminatorValue>;
185
271
  }): Simplify<Partial<z.input<TSchema>>>;
186
272
 
187
- declare function extractFieldFromSchema<TSchema extends z$1.ZodType, TName extends keyof Extract<Required<z$1.input<TSchema>>, Record<TDiscriminatorKey, TDiscriminatorValue>>, TDiscriminatorKey extends keyof z$1.input<TSchema> & string, TDiscriminatorValue extends z$1.input<TSchema>[TDiscriminatorKey] & util.Literal>({ schema, fieldName, discriminator, }: {
273
+ /**
274
+ * Recursively extracts the exact schema type from a discriminated union based on the discriminator value.
275
+ *
276
+ * This advanced TypeScript utility type walks through a union's options tuple at compile-time,
277
+ * checking each schema against the discriminator field and value, and returns the exact matching
278
+ * schema type (not a union of all options).
279
+ *
280
+ * **How it works:**
281
+ * 1. Extracts the options tuple from the union using `infer Options`
282
+ * 2. Destructure into head (`First`) and tail (`Rest`) using tuple pattern matching
283
+ * 3. Checks if `First` is a ZodObject with the matching discriminator field and value
284
+ * 4. If match found, returns `First` (the exact schema type)
285
+ * 5. If no match, recursively processes `Rest` until a match is found or list is exhausted
286
+ *
287
+ * **Type narrowing magic:**
288
+ * - Input: `z.discriminatedUnion('type', [SchemaA, SchemaB, SchemaC])`
289
+ * - Discriminator value: `'a'` (matches SchemaA)
290
+ * - Output: `SchemaA` (exact type, not `SchemaA | SchemaB | SchemaC`)
291
+ *
292
+ * @template TSchema - The ZodUnion or ZodDiscriminatedUnion type
293
+ * @template TDiscriminatorKey - The discriminator field name (e.g., "type", "mode")
294
+ * @template TDiscriminatorValue - The specific discriminator value (e.g., "create", "edit")
295
+ * @returns The exact matching schema type, or `never` if no match found
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * const schema = z.discriminatedUnion('mode', [
300
+ * z.object({ mode: z.literal('create'), name: z.string() }),
301
+ * z.object({ mode: z.literal('edit'), id: z.number() }),
302
+ * ]);
303
+ *
304
+ * // Exact type: z.object({ mode: z.literal('create'), name: z.string() })
305
+ * type CreateSchema = ExtractZodUnionMember<typeof schema, 'mode', 'create'>;
306
+ * ```
307
+ */
308
+ type ExtractZodUnionMember<TSchema extends z$1.ZodUnion | z$1.ZodDiscriminatedUnion, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends z$1.input<TSchema>[TDiscriminatorKey] & util.Literal> = TSchema extends z$1.ZodUnion<infer Options> ? Options extends readonly [
309
+ infer First extends z$1.ZodTypeAny,
310
+ ...infer Rest extends z$1.ZodTypeAny[]
311
+ ] ? First extends z$1.ZodObject<infer Shape> ? TDiscriminatorKey extends keyof Shape ? Shape[TDiscriminatorKey] extends z$1.ZodLiteral<TDiscriminatorValue> | z$1.ZodDefault<z$1.ZodLiteral<TDiscriminatorValue>> ? First : Rest extends [] ? never : TDiscriminatorValue extends $InferUnionInput<Rest[number]>[TDiscriminatorKey] ? ExtractZodUnionMember<z$1.ZodUnion<Rest>, TDiscriminatorKey, TDiscriminatorValue> : never : Rest extends [] ? never : TDiscriminatorValue extends $InferUnionInput<Rest[number]>[TDiscriminatorKey] ? ExtractZodUnionMember<z$1.ZodUnion<Rest>, TDiscriminatorKey, TDiscriminatorValue> : never : never : never : never;
312
+ /**
313
+ * Extracts a specific schema option from a discriminated union based on the discriminator field value.
314
+ *
315
+ * This function finds and returns the **exact matching schema** from a `ZodDiscriminatedUnion` by
316
+ * comparing the discriminator field value. It's used internally by {@link getSchemaDefaults} to
317
+ * extract defaults from the correct schema variant in a discriminated union.
318
+ *
319
+ * **Key feature:** Returns the **exact schema type**, not a union of all options, thanks to the
320
+ * {@link ExtractZodUnionMember} recursive type utility. This enables precise type narrowing at
321
+ * compile-time based on the discriminator value.
322
+ *
323
+ * **How it works:**
324
+ * 1. Iterates through all options in the discriminated union at runtime
325
+ * 2. For each option, validates it's a ZodObject and checks if the discriminator field matches
326
+ * 3. Returns the first matching schema with its exact type narrowed at compile-time
327
+ * 4. Returns `undefined` if no match found or if option is not a ZodObject
328
+ *
329
+ * @template TSchema - The ZodUnion or ZodDiscriminatedUnion schema type
330
+ * @template TDiscriminatorKey - The discriminator field name (string key of the inferred union type)
331
+ * @template TDiscriminatorValue - The specific discriminator value to match (literal type)
332
+ * @param params - Parameters object
333
+ * @param params.schema - The discriminated union schema to search
334
+ * @param params.discriminatorKey - The discriminator field name (e.g., "mode", "type")
335
+ * @param params.discriminatorValue - The discriminator value to match (e.g., "create", "edit")
336
+ * @returns The exact matching schema option (with precise type), or `undefined` if not found
337
+ *
338
+ * @example
339
+ * Basic discriminated union - create/edit mode
340
+ * ```typescript
341
+ * const userSchema = z.discriminatedUnion('mode', [
342
+ * z.object({
343
+ * mode: z.literal('create'),
344
+ * name: z.string(),
345
+ * age: z.number().optional(),
346
+ * }),
347
+ * z.object({
348
+ * mode: z.literal('edit'),
349
+ * id: z.number(),
350
+ * name: z.string().optional(),
351
+ * }),
352
+ * ]);
353
+ *
354
+ * // Extract the "create" schema
355
+ * const createSchema = extractDiscriminatedSchema({
356
+ * schema: userSchema,
357
+ * discriminatorKey: 'mode',
358
+ * discriminatorValue: 'create',
359
+ * });
360
+ * // Result: z.object({ mode: z.literal('create'), name: z.string(), age: z.number().optional() })
361
+ *
362
+ * // Extract the "edit" schema
363
+ * const editSchema = extractDiscriminatedSchema({
364
+ * schema: userSchema,
365
+ * discriminatorKey: 'mode',
366
+ * discriminatorValue: 'edit',
367
+ * });
368
+ * // Result: z.object({ mode: z.literal('edit'), id: z.number(), name: z.string().optional() })
369
+ * ```
370
+ *
371
+ * @example
372
+ * Type-based discrimination
373
+ * ```typescript
374
+ * const eventSchema = z.discriminatedUnion('type', [
375
+ * z.object({ type: z.literal('click'), x: z.number(), y: z.number() }),
376
+ * z.object({ type: z.literal('keypress'), key: z.string() }),
377
+ * ]);
378
+ *
379
+ * const clickSchema = extractDiscriminatedSchema({
380
+ * schema: eventSchema,
381
+ * discriminatorKey: 'type',
382
+ * discriminatorValue: 'click',
383
+ * });
384
+ * // Result: z.object({ type: z.literal('click'), x: z.number(), y: z.number() })
385
+ * ```
386
+ *
387
+ * @example
388
+ * Invalid discriminator value
389
+ * ```typescript
390
+ * const schema = z.discriminatedUnion('mode', [
391
+ * z.object({ mode: z.literal('create'), name: z.string() }),
392
+ * ]);
393
+ *
394
+ * const result = extractDiscriminatedSchema({
395
+ * schema,
396
+ * discriminatorKey: 'mode',
397
+ * discriminatorValue: 'invalid', // doesn't match any option
398
+ * });
399
+ * // Result: undefined
400
+ * ```
401
+ *
402
+ * @example
403
+ * Type narrowing demonstration
404
+ * ```typescript
405
+ * const schema = z.discriminatedUnion('mode', [
406
+ * z.object({ mode: z.literal('create'), name: z.string(), age: z.number() }),
407
+ * z.object({ mode: z.literal('edit'), id: z.number(), bio: z.string() }),
408
+ * ]);
409
+ *
410
+ * const createSchema = extractDiscriminatedSchema({
411
+ * schema,
412
+ * discriminatorKey: 'mode',
413
+ * discriminatorValue: 'create',
414
+ * });
415
+ *
416
+ * // Type is EXACTLY: z.object({ mode: z.literal('create'), name: z.string(), age: z.number() })
417
+ * // NOT: z.object({ mode: ..., ... }) | z.object({ mode: ..., ... }) | undefined
418
+ *
419
+ * if (createSchema) {
420
+ * createSchema.shape.age; // ✅ TypeScript knows 'age' exists
421
+ * createSchema.shape.name; // ✅ TypeScript knows 'name' exists
422
+ * // createSchema.shape.id; // ❌ TypeScript error: 'id' doesn't exist on 'create' schema
423
+ * }
424
+ * ```
425
+ *
426
+ * @see {@link getSchemaDefaults} for usage with discriminated unions
427
+ * @see {@link ExtractZodUnionMember} for the type-level extraction logic
428
+ * @since 0.6.0
429
+ */
430
+ declare const extractDiscriminatedSchema: <TSchema extends z$1.ZodType, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends DiscriminatorValue<TSchema, TDiscriminatorKey>, ReturnType extends TSchema extends z$1.ZodDiscriminatedUnion ? ExtractZodUnionMember<TSchema, TDiscriminatorKey, TDiscriminatorValue> : never>({ schema, key, value, }: {
431
+ schema: TSchema;
432
+ } & Discriminator<TSchema, TDiscriminatorKey, TDiscriminatorValue>) => ReturnType;
433
+
434
+ type Split<S extends string> = S extends `${infer Head}.${infer Tail}` ? [Head, ...Split<Tail>] : [S];
435
+ type IsNumeric<S extends string> = S extends `${number}` ? true : false;
436
+ type Unwrap<T> = T extends z$1.ZodOptional<infer U> ? Unwrap<U> : T extends z$1.ZodNullable<infer U> ? Unwrap<U> : T extends z$1.ZodDefault<infer U> ? Unwrap<U> : T;
437
+ type NavigateZod<T, Path extends string[]> = Path extends [
438
+ infer First extends string,
439
+ ...infer Rest extends string[]
440
+ ] ? Unwrap<T> extends z$1.ZodObject<infer Shape> ? First extends keyof Shape ? Rest extends [] ? Shape[First] : NavigateZod<Shape[First], Rest> : never : Unwrap<T> extends z$1.ZodArray<infer Element> ? IsNumeric<First> extends true ? Rest extends [] ? Element : NavigateZod<Element, Rest> : never : never : T;
441
+ type ExtractZodByPath<Schema, Path extends string> = NavigateZod<Schema, Split<Path>>;
442
+ declare function extractFieldFromSchema<TSchema extends z$1.ZodType, TPath extends ValidPaths<TSchema, TDiscriminatorKey, TDiscriminatorValue>, TDiscriminatorKey extends DiscriminatorKey<TSchema>, TDiscriminatorValue extends DiscriminatorValue<TSchema, TDiscriminatorKey>>({ schema, name, discriminator, }: {
188
443
  schema: TSchema;
189
- fieldName: TName;
190
- discriminator?: {
191
- key: TDiscriminatorKey;
192
- value: TDiscriminatorValue;
193
- };
194
- }): z$1.ZodType<unknown, unknown, z$1.core.$ZodTypeInternals<unknown, unknown>> | undefined;
444
+ name: TPath;
445
+ discriminator?: Discriminator<TSchema, TDiscriminatorKey, TDiscriminatorValue>;
446
+ }): (ExtractZodByPath<TSchema, TPath> & z$1.ZodType) | undefined;
447
+ /**
448
+ * Extends a Zod field with a transformation while preserving its metadata.
449
+ *
450
+ * This is useful when you want to add validations or transformations to a field
451
+ * but keep the original metadata (like translationKey) intact.
452
+ *
453
+ * @param field - The original Zod field
454
+ * @param transform - A function that transforms the field
455
+ * @returns The transformed field with preserved metadata
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * const baseField = z.string().meta({ translationKey: 'user.field.name' });
460
+ *
461
+ * // Add min/max validation while keeping the translationKey
462
+ * const extendedField = extendWithMeta(baseField, (f) => f.min(3).max(100));
463
+ * extendedField.meta(); // { translationKey: 'user.field.name' }
464
+ * ```
465
+ */
466
+ declare function extendWithMeta<T extends z$1.ZodType, R extends z$1.ZodType>(field: T, transform: (f: T) => R): R;
195
467
 
196
468
  /**
197
469
  * Type representing a Zod type that has an unwrap method
198
470
  */
199
471
  type Unwrappable = {
200
- unwrap: () => z.ZodTypeAny;
472
+ unwrap: () => z$1.ZodTypeAny;
201
473
  };
202
474
  /**
203
475
  * Type guard to check if a Zod field can be unwrapped (has wrapper types like optional, nullable, default).
@@ -219,7 +491,7 @@ type Unwrappable = {
219
491
  *
220
492
  * @since 0.1.0
221
493
  */
222
- declare function canUnwrap(field: z.ZodTypeAny): field is z.ZodTypeAny & Unwrappable;
494
+ declare function canUnwrap(field: z$1.ZodTypeAny): field is z$1.ZodTypeAny & Unwrappable;
223
495
  /**
224
496
  * Attempts to strip nullish types from a union and return the single remaining type.
225
497
  *
@@ -257,7 +529,7 @@ declare function canUnwrap(field: z.ZodTypeAny): field is z.ZodTypeAny & Unwrapp
257
529
  * @see {@link getPrimitiveType} for unwrapping wrapper types
258
530
  * @since 0.5.0
259
531
  */
260
- declare function tryStripNullishOnly(field: z.ZodTypeAny): z.ZodType | false;
532
+ declare function tryStripNullishOnly(field: z$1.ZodTypeAny): z$1.ZodType | false;
261
533
  /**
262
534
  * Gets the underlying primitive type of a Zod field by recursively unwrapping wrapper types.
263
535
  *
@@ -316,8 +588,8 @@ declare function tryStripNullishOnly(field: z.ZodTypeAny): z.ZodType | false;
316
588
  * @see {@link tryStripNullishOnly} for union nullish stripping logic
317
589
  * @since 0.1.0
318
590
  */
319
- declare const getPrimitiveType: <T extends z.ZodType>(field: T) => z.ZodTypeAny;
320
- type StripZodDefault<T> = T extends z.ZodDefault<infer Inner> ? StripZodDefault<Inner> : T extends z.ZodOptional<infer Inner> ? z.ZodOptional<StripZodDefault<Inner>> : T extends z.ZodNullable<infer Inner> ? z.ZodNullable<StripZodDefault<Inner>> : T;
591
+ declare const getPrimitiveType: <T extends z$1.ZodType>(field: T) => z$1.ZodTypeAny;
592
+ type StripZodDefault<T> = T extends z$1.ZodDefault<infer Inner> ? StripZodDefault<Inner> : T extends z$1.ZodOptional<infer Inner> ? z$1.ZodOptional<StripZodDefault<Inner>> : T extends z$1.ZodNullable<infer Inner> ? z$1.ZodNullable<StripZodDefault<Inner>> : T;
321
593
  /**
322
594
  * Removes default values from a Zod field while preserving other wrapper types.
323
595
  *
@@ -356,7 +628,7 @@ type StripZodDefault<T> = T extends z.ZodDefault<infer Inner> ? StripZodDefault<
356
628
  * @see {@link requiresValidInput} for usage with requirement checking
357
629
  * @since 0.1.0
358
630
  */
359
- declare function removeDefault<T extends z.ZodType>(field: T): StripZodDefault<T>;
631
+ declare function removeDefault<T extends z$1.ZodType>(field: T): StripZodDefault<T>;
360
632
  /**
361
633
  * Determines if a field will show validation errors when the user submits empty or invalid input.
362
634
  *
@@ -434,7 +706,7 @@ declare function removeDefault<T extends z.ZodType>(field: T): StripZodDefault<T
434
706
  * @see {@link getPrimitiveType} for understanding type unwrapping
435
707
  * @since 0.1.0
436
708
  */
437
- declare const requiresValidInput: <T extends z.ZodType>(field: T) => boolean;
709
+ declare const requiresValidInput: <T extends z$1.ZodType>(field: T) => boolean;
438
710
  /**
439
711
  * Union type of all Zod check definition types.
440
712
  *
@@ -524,168 +796,6 @@ type ZodUnionCheck = $ZodCheckLessThanDef | $ZodCheckGreaterThanDef | $ZodCheckM
524
796
  * @see {@link ZodUnionCheck} for all supported check types
525
797
  * @since 0.4.0
526
798
  */
527
- declare function getFieldChecks<T extends z.ZodTypeAny>(field: T): Array<ZodUnionCheck>;
528
- /**
529
- * Recursively extracts the exact schema type from a discriminated union based on the discriminator value.
530
- *
531
- * This advanced TypeScript utility type walks through a union's options tuple at compile-time,
532
- * checking each schema against the discriminator field and value, and returns the exact matching
533
- * schema type (not a union of all options).
534
- *
535
- * **How it works:**
536
- * 1. Extracts the options tuple from the union using `infer Options`
537
- * 2. Destructure into head (`First`) and tail (`Rest`) using tuple pattern matching
538
- * 3. Checks if `First` is a ZodObject with the matching discriminator field and value
539
- * 4. If match found, returns `First` (the exact schema type)
540
- * 5. If no match, recursively processes `Rest` until a match is found or list is exhausted
541
- *
542
- * **Type narrowing magic:**
543
- * - Input: `z.discriminatedUnion('type', [SchemaA, SchemaB, SchemaC])`
544
- * - Discriminator value: `'a'` (matches SchemaA)
545
- * - Output: `SchemaA` (exact type, not `SchemaA | SchemaB | SchemaC`)
546
- *
547
- * @template TSchema - The ZodUnion or ZodDiscriminatedUnion type
548
- * @template TDiscriminatorKey - The discriminator field name (e.g., "type", "mode")
549
- * @template TDiscriminatorValue - The specific discriminator value (e.g., "create", "edit")
550
- * @returns The exact matching schema type, or `never` if no match found
551
- *
552
- * @example
553
- * ```typescript
554
- * const schema = z.discriminatedUnion('mode', [
555
- * z.object({ mode: z.literal('create'), name: z.string() }),
556
- * z.object({ mode: z.literal('edit'), id: z.number() }),
557
- * ]);
558
- *
559
- * // Exact type: z.object({ mode: z.literal('create'), name: z.string() })
560
- * type CreateSchema = ExtractZodUnionMember<typeof schema, 'mode', 'create'>;
561
- * ```
562
- */
563
- type ExtractZodUnionMember<TSchema extends z.ZodUnion | z.ZodDiscriminatedUnion, TDiscriminatorKey extends keyof z.input<TSchema> & string, TDiscriminatorValue extends z.input<TSchema>[TDiscriminatorKey] & util.Literal> = TSchema extends z.ZodUnion<infer Options> ? Options extends readonly [
564
- infer First extends z.ZodTypeAny,
565
- ...infer Rest extends z.ZodTypeAny[]
566
- ] ? First extends z.ZodObject<infer Shape> ? TDiscriminatorKey extends keyof Shape ? Shape[TDiscriminatorKey] extends z.ZodLiteral<TDiscriminatorValue> ? First : Rest extends [] ? never : TDiscriminatorValue extends $InferUnionInput<Rest[number]>[TDiscriminatorKey] ? ExtractZodUnionMember<z.ZodUnion<Rest>, TDiscriminatorKey, TDiscriminatorValue> : never : Rest extends [] ? never : TDiscriminatorValue extends $InferUnionInput<Rest[number]>[TDiscriminatorKey] ? ExtractZodUnionMember<z.ZodUnion<Rest>, TDiscriminatorKey, TDiscriminatorValue> : never : never : never : never;
567
- /**
568
- * Extracts a specific schema option from a discriminated union based on the discriminator field value.
569
- *
570
- * This function finds and returns the **exact matching schema** from a `ZodDiscriminatedUnion` by
571
- * comparing the discriminator field value. It's used internally by {@link getSchemaDefaults} to
572
- * extract defaults from the correct schema variant in a discriminated union.
573
- *
574
- * **Key feature:** Returns the **exact schema type**, not a union of all options, thanks to the
575
- * {@link ExtractZodUnionMember} recursive type utility. This enables precise type narrowing at
576
- * compile-time based on the discriminator value.
577
- *
578
- * **How it works:**
579
- * 1. Iterates through all options in the discriminated union at runtime
580
- * 2. For each option, validates it's a ZodObject and checks if the discriminator field matches
581
- * 3. Returns the first matching schema with its exact type narrowed at compile-time
582
- * 4. Returns `undefined` if no match found or if option is not a ZodObject
583
- *
584
- * @template TSchema - The ZodUnion or ZodDiscriminatedUnion schema type
585
- * @template TDiscriminatorKey - The discriminator field name (string key of the inferred union type)
586
- * @template TDiscriminatorValue - The specific discriminator value to match (literal type)
587
- * @param params - Parameters object
588
- * @param params.schema - The discriminated union schema to search
589
- * @param params.discriminatorKey - The discriminator field name (e.g., "mode", "type")
590
- * @param params.discriminatorValue - The discriminator value to match (e.g., "create", "edit")
591
- * @returns The exact matching schema option (with precise type), or `undefined` if not found
592
- *
593
- * @example
594
- * Basic discriminated union - create/edit mode
595
- * ```typescript
596
- * const userSchema = z.discriminatedUnion('mode', [
597
- * z.object({
598
- * mode: z.literal('create'),
599
- * name: z.string(),
600
- * age: z.number().optional(),
601
- * }),
602
- * z.object({
603
- * mode: z.literal('edit'),
604
- * id: z.number(),
605
- * name: z.string().optional(),
606
- * }),
607
- * ]);
608
- *
609
- * // Extract the "create" schema
610
- * const createSchema = extractDiscriminatedSchema({
611
- * schema: userSchema,
612
- * discriminatorKey: 'mode',
613
- * discriminatorValue: 'create',
614
- * });
615
- * // Result: z.object({ mode: z.literal('create'), name: z.string(), age: z.number().optional() })
616
- *
617
- * // Extract the "edit" schema
618
- * const editSchema = extractDiscriminatedSchema({
619
- * schema: userSchema,
620
- * discriminatorKey: 'mode',
621
- * discriminatorValue: 'edit',
622
- * });
623
- * // Result: z.object({ mode: z.literal('edit'), id: z.number(), name: z.string().optional() })
624
- * ```
625
- *
626
- * @example
627
- * Type-based discrimination
628
- * ```typescript
629
- * const eventSchema = z.discriminatedUnion('type', [
630
- * z.object({ type: z.literal('click'), x: z.number(), y: z.number() }),
631
- * z.object({ type: z.literal('keypress'), key: z.string() }),
632
- * ]);
633
- *
634
- * const clickSchema = extractDiscriminatedSchema({
635
- * schema: eventSchema,
636
- * discriminatorKey: 'type',
637
- * discriminatorValue: 'click',
638
- * });
639
- * // Result: z.object({ type: z.literal('click'), x: z.number(), y: z.number() })
640
- * ```
641
- *
642
- * @example
643
- * Invalid discriminator value
644
- * ```typescript
645
- * const schema = z.discriminatedUnion('mode', [
646
- * z.object({ mode: z.literal('create'), name: z.string() }),
647
- * ]);
648
- *
649
- * const result = extractDiscriminatedSchema({
650
- * schema,
651
- * discriminatorKey: 'mode',
652
- * discriminatorValue: 'invalid', // doesn't match any option
653
- * });
654
- * // Result: undefined
655
- * ```
656
- *
657
- * @example
658
- * Type narrowing demonstration
659
- * ```typescript
660
- * const schema = z.discriminatedUnion('mode', [
661
- * z.object({ mode: z.literal('create'), name: z.string(), age: z.number() }),
662
- * z.object({ mode: z.literal('edit'), id: z.number(), bio: z.string() }),
663
- * ]);
664
- *
665
- * const createSchema = extractDiscriminatedSchema({
666
- * schema,
667
- * discriminatorKey: 'mode',
668
- * discriminatorValue: 'create',
669
- * });
670
- *
671
- * // Type is EXACTLY: z.object({ mode: z.literal('create'), name: z.string(), age: z.number() })
672
- * // NOT: z.object({ mode: ..., ... }) | z.object({ mode: ..., ... }) | undefined
673
- *
674
- * if (createSchema) {
675
- * createSchema.shape.age; // ✅ TypeScript knows 'age' exists
676
- * createSchema.shape.name; // ✅ TypeScript knows 'name' exists
677
- * // createSchema.shape.id; // ❌ TypeScript error: 'id' doesn't exist on 'create' schema
678
- * }
679
- * ```
680
- *
681
- * @see {@link getSchemaDefaults} for usage with discriminated unions
682
- * @see {@link ExtractZodUnionMember} for the type-level extraction logic
683
- * @since 0.6.0
684
- */
685
- declare const extractDiscriminatedSchema: <TSchema extends z.ZodUnion | z.ZodDiscriminatedUnion, TDiscriminatorKey extends keyof z.input<TSchema> & string, TDiscriminatorValue extends z.input<TSchema>[TDiscriminatorKey] & util.Literal>({ schema, key, value, }: {
686
- schema: TSchema;
687
- key: TDiscriminatorKey;
688
- value: TDiscriminatorValue;
689
- }) => ExtractZodUnionMember<TSchema, TDiscriminatorKey, TDiscriminatorValue> | undefined;
799
+ declare function getFieldChecks<T extends z$1.ZodTypeAny>(field: T): Array<ZodUnionCheck>;
690
800
 
691
- export { type Simplify, type ZodUnionCheck, canUnwrap, extractDefaultValue, extractDiscriminatedSchema, extractFieldFromSchema, getFieldChecks, getPrimitiveType, getSchemaDefaults, removeDefault, requiresValidInput, tryStripNullishOnly };
801
+ export { type CommonFields, type Discriminator, type DiscriminatorKey, type DiscriminatorValue, type ExtractZodByPath, type Paths, type Simplify, type ValidPaths, type ZodUnionCheck, canUnwrap, extendWithMeta, extractDefaultValue, extractDiscriminatedSchema, extractFieldFromSchema, getFieldChecks, getPrimitiveType, getSchemaDefaults, removeDefault, requiresValidInput, tryStripNullishOnly };