@zod-utils/core 0.9.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -9
- package/dist/index.d.mts +112 -33
- package/dist/index.d.ts +112 -33
- package/dist/index.js +68 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@ npm install @zod-utils/core zod
|
|
|
35
35
|
|
|
36
36
|
Extract all default values from a Zod object schema. Only extracts fields that explicitly have `.default()` on them.
|
|
37
37
|
|
|
38
|
+
**Transform support:** Works with schemas that have `.transform()` - extracts defaults from the input type.
|
|
39
|
+
|
|
38
40
|
```typescript
|
|
39
41
|
import { getSchemaDefaults } from "@zod-utils/core";
|
|
40
42
|
import { z } from "zod";
|
|
@@ -137,9 +139,11 @@ requiresValidInput(middleName); // false - user can leave null
|
|
|
137
139
|
|
|
138
140
|
### `getPrimitiveType(field)`
|
|
139
141
|
|
|
140
|
-
Get the primitive type of a Zod field by unwrapping optional/nullable wrappers.
|
|
142
|
+
Get the primitive type of a Zod field by unwrapping optional/nullable/transform wrappers.
|
|
141
143
|
Stops at arrays without unwrapping them.
|
|
142
144
|
|
|
145
|
+
**Transform support:** Automatically unwraps `.transform()` to get the underlying input type.
|
|
146
|
+
|
|
143
147
|
```typescript
|
|
144
148
|
import { getPrimitiveType } from "@zod-utils/core";
|
|
145
149
|
import { z } from "zod";
|
|
@@ -151,6 +155,11 @@ const primitive = getPrimitiveType(field);
|
|
|
151
155
|
const arrayField = z.array(z.string()).optional();
|
|
152
156
|
const arrayPrimitive = getPrimitiveType(arrayField);
|
|
153
157
|
// Returns the ZodArray (stops at arrays)
|
|
158
|
+
|
|
159
|
+
// Transform support
|
|
160
|
+
const transformed = z.string().transform((val) => val.toUpperCase());
|
|
161
|
+
const primitiveFromTransform = getPrimitiveType(transformed);
|
|
162
|
+
// Returns the underlying ZodString (unwraps the transform)
|
|
154
163
|
```
|
|
155
164
|
|
|
156
165
|
---
|
|
@@ -172,34 +181,40 @@ withoutDefault.parse(undefined); // throws error
|
|
|
172
181
|
|
|
173
182
|
---
|
|
174
183
|
|
|
175
|
-
### `
|
|
184
|
+
### `extractDefaultValue(field)`
|
|
176
185
|
|
|
177
|
-
Extract the default value from a Zod field (recursively unwraps optional/nullable/union layers).
|
|
186
|
+
Extract the default value from a Zod field (recursively unwraps optional/nullable/union/transform layers).
|
|
178
187
|
|
|
179
188
|
**Union handling:** For union types, extracts the default from the first option. If the first option has no default, returns `undefined` (defaults in other union options are not checked).
|
|
180
189
|
|
|
190
|
+
**Transform support:** Automatically unwraps `.transform()` to get the input type's default value.
|
|
191
|
+
|
|
181
192
|
```typescript
|
|
182
|
-
import {
|
|
193
|
+
import { extractDefaultValue } from "@zod-utils/core";
|
|
183
194
|
import { z } from "zod";
|
|
184
195
|
|
|
185
196
|
// Basic usage
|
|
186
197
|
const field = z.string().optional().default("hello");
|
|
187
|
-
|
|
198
|
+
extractDefaultValue(field); // 'hello'
|
|
188
199
|
|
|
189
200
|
const noDefault = z.string();
|
|
190
|
-
|
|
201
|
+
extractDefaultValue(noDefault); // undefined
|
|
191
202
|
|
|
192
203
|
// Union with default in first option
|
|
193
204
|
const unionField = z.union([z.string().default('hello'), z.number()]);
|
|
194
|
-
|
|
205
|
+
extractDefaultValue(unionField); // 'hello'
|
|
195
206
|
|
|
196
207
|
// Union with default in second option (only checks first)
|
|
197
208
|
const unionField2 = z.union([z.string(), z.number().default(42)]);
|
|
198
|
-
|
|
209
|
+
extractDefaultValue(unionField2); // undefined
|
|
199
210
|
|
|
200
211
|
// Union wrapped in optional
|
|
201
212
|
const wrappedUnion = z.union([z.string().default('test'), z.number()]).optional();
|
|
202
|
-
|
|
213
|
+
extractDefaultValue(wrappedUnion); // 'test'
|
|
214
|
+
|
|
215
|
+
// Transform support - extracts input default, not output
|
|
216
|
+
const transformed = z.string().default('hello').transform((val) => val.toUpperCase());
|
|
217
|
+
extractDefaultValue(transformed); // 'hello' (not 'HELLO')
|
|
203
218
|
```
|
|
204
219
|
|
|
205
220
|
---
|
|
@@ -272,6 +287,173 @@ import { getFieldChecks, type ZodUnionCheck } from "@zod-utils/core";
|
|
|
272
287
|
|
|
273
288
|
---
|
|
274
289
|
|
|
290
|
+
### `extractDiscriminatedSchema(schema, key, value)`
|
|
291
|
+
|
|
292
|
+
Extract a specific variant from a discriminated union schema based on the discriminator field and value.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { extractDiscriminatedSchema } from "@zod-utils/core";
|
|
296
|
+
import { z } from "zod";
|
|
297
|
+
|
|
298
|
+
const userSchema = z.discriminatedUnion('mode', [
|
|
299
|
+
z.object({
|
|
300
|
+
mode: z.literal('create'),
|
|
301
|
+
name: z.string(),
|
|
302
|
+
age: z.number().optional(),
|
|
303
|
+
}),
|
|
304
|
+
z.object({
|
|
305
|
+
mode: z.literal('edit'),
|
|
306
|
+
id: z.number(),
|
|
307
|
+
name: z.string().optional(),
|
|
308
|
+
bio: z.string().optional(),
|
|
309
|
+
}),
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
// Extract the 'create' variant
|
|
313
|
+
const createSchema = extractDiscriminatedSchema({
|
|
314
|
+
schema: userSchema,
|
|
315
|
+
key: 'mode',
|
|
316
|
+
value: 'create',
|
|
317
|
+
});
|
|
318
|
+
// Returns: z.ZodObject with { mode, name, age }
|
|
319
|
+
|
|
320
|
+
// Extract the 'edit' variant
|
|
321
|
+
const editSchema = extractDiscriminatedSchema({
|
|
322
|
+
schema: userSchema,
|
|
323
|
+
key: 'mode',
|
|
324
|
+
value: 'edit',
|
|
325
|
+
});
|
|
326
|
+
// Returns: z.ZodObject with { mode, id, name, bio }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Use with discriminated unions:** This is essential when working with `z.discriminatedUnion()` schemas, as it extracts the correct variant schema based on the discriminator value.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
### `extractFieldFromSchema(schema, fieldName, discriminator?)`
|
|
334
|
+
|
|
335
|
+
Extract a single field from a Zod object or discriminated union schema.
|
|
336
|
+
|
|
337
|
+
**Transform support:** Works with schemas that have `.transform()` - extracts fields from the input type.
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { extractFieldFromSchema } from "@zod-utils/core";
|
|
341
|
+
import { z } from "zod";
|
|
342
|
+
|
|
343
|
+
// Simple object schema
|
|
344
|
+
const userSchema = z.object({
|
|
345
|
+
name: z.string(),
|
|
346
|
+
age: z.number(),
|
|
347
|
+
email: z.string().email(),
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const nameField = extractFieldFromSchema({
|
|
351
|
+
schema: userSchema,
|
|
352
|
+
fieldName: 'name',
|
|
353
|
+
});
|
|
354
|
+
// Returns: ZodString
|
|
355
|
+
|
|
356
|
+
// Discriminated union schema
|
|
357
|
+
const formSchema = z.discriminatedUnion('mode', [
|
|
358
|
+
z.object({
|
|
359
|
+
mode: z.literal('create'),
|
|
360
|
+
name: z.string(),
|
|
361
|
+
age: z.number().optional(),
|
|
362
|
+
}),
|
|
363
|
+
z.object({
|
|
364
|
+
mode: z.literal('edit'),
|
|
365
|
+
id: z.number(),
|
|
366
|
+
name: z.string().optional(),
|
|
367
|
+
}),
|
|
368
|
+
]);
|
|
369
|
+
|
|
370
|
+
// Extract field from specific variant
|
|
371
|
+
const idField = extractFieldFromSchema({
|
|
372
|
+
schema: formSchema,
|
|
373
|
+
fieldName: 'id',
|
|
374
|
+
discriminator: {
|
|
375
|
+
key: 'mode',
|
|
376
|
+
value: 'edit',
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
// Returns: ZodNumber
|
|
380
|
+
|
|
381
|
+
// Without discriminator on discriminated union, returns undefined
|
|
382
|
+
const fieldWithoutDiscriminator = extractFieldFromSchema({
|
|
383
|
+
schema: formSchema,
|
|
384
|
+
fieldName: 'name',
|
|
385
|
+
});
|
|
386
|
+
// Returns: undefined (need discriminator to know which variant)
|
|
387
|
+
|
|
388
|
+
// Works with transforms - extracts from input type
|
|
389
|
+
const transformedSchema = z
|
|
390
|
+
.object({
|
|
391
|
+
name: z.string(),
|
|
392
|
+
age: z.number(),
|
|
393
|
+
})
|
|
394
|
+
.transform((data) => ({ ...data, computed: true }));
|
|
395
|
+
|
|
396
|
+
const nameFromTransformed = extractFieldFromSchema({
|
|
397
|
+
schema: transformedSchema,
|
|
398
|
+
fieldName: 'name',
|
|
399
|
+
});
|
|
400
|
+
// Returns: ZodString (from the input type, not affected by transform)
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Discriminated union support:** When extracting fields from discriminated unions, you must provide the `discriminator` option with `key` and `value` to specify which variant to use.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
### `getSchemaDefaults(schema, discriminator?)`
|
|
408
|
+
|
|
409
|
+
**Updated:** Now supports discriminated union schemas with the `discriminator` option.
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { getSchemaDefaults } from "@zod-utils/core";
|
|
413
|
+
import { z } from "zod";
|
|
414
|
+
|
|
415
|
+
// Discriminated union with defaults
|
|
416
|
+
const formSchema = z.discriminatedUnion('mode', [
|
|
417
|
+
z.object({
|
|
418
|
+
mode: z.literal('create'),
|
|
419
|
+
name: z.string(),
|
|
420
|
+
age: z.number().default(18),
|
|
421
|
+
}),
|
|
422
|
+
z.object({
|
|
423
|
+
mode: z.literal('edit'),
|
|
424
|
+
id: z.number().default(1),
|
|
425
|
+
name: z.string().optional(),
|
|
426
|
+
bio: z.string().default('bio goes here'),
|
|
427
|
+
}),
|
|
428
|
+
]);
|
|
429
|
+
|
|
430
|
+
// Get defaults for 'create' mode
|
|
431
|
+
const createDefaults = getSchemaDefaults(formSchema, {
|
|
432
|
+
discriminator: {
|
|
433
|
+
key: 'mode',
|
|
434
|
+
value: 'create',
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
// Returns: { age: 18 }
|
|
438
|
+
|
|
439
|
+
// Get defaults for 'edit' mode
|
|
440
|
+
const editDefaults = getSchemaDefaults(formSchema, {
|
|
441
|
+
discriminator: {
|
|
442
|
+
key: 'mode',
|
|
443
|
+
value: 'edit',
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
// Returns: { id: 1, bio: 'bio goes here' }
|
|
447
|
+
|
|
448
|
+
// Without discriminator, returns empty object
|
|
449
|
+
const noDefaults = getSchemaDefaults(formSchema);
|
|
450
|
+
// Returns: {}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Discriminator types:** The discriminator `value` can be a string, number, or boolean literal that matches the discriminator field type.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
275
457
|
## Type Utilities
|
|
276
458
|
|
|
277
459
|
### `Simplify<T>`
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as z from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { util, z as z$1 } from 'zod';
|
|
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';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Simplifies complex TypeScript types for better IDE hover tooltips and error messages.
|
|
@@ -34,8 +35,8 @@ import { $ZodCheckLessThanDef, $ZodCheckGreaterThanDef, $ZodCheckMultipleOfDef,
|
|
|
34
35
|
* const schema = z.object({ id: z.string() })
|
|
35
36
|
* .merge(z.object({ name: z.string() }));
|
|
36
37
|
*
|
|
37
|
-
* type InferredType = z.
|
|
38
|
-
* type SimplifiedType = Simplify<z.
|
|
38
|
+
* type InferredType = z.input<typeof schema>; // May show complex type
|
|
39
|
+
* type SimplifiedType = Simplify<z.input<typeof schema>>;
|
|
39
40
|
* // Shows clear: { id: string; name: string }
|
|
40
41
|
* ```
|
|
41
42
|
*
|
|
@@ -63,7 +64,7 @@ type Simplify<T> = {
|
|
|
63
64
|
* Basic usage with default value
|
|
64
65
|
* ```typescript
|
|
65
66
|
* const field = z.string().default('hello');
|
|
66
|
-
* const defaultValue =
|
|
67
|
+
* const defaultValue = extractDefaultValue(field);
|
|
67
68
|
* // Result: 'hello'
|
|
68
69
|
* ```
|
|
69
70
|
*
|
|
@@ -71,7 +72,7 @@ type Simplify<T> = {
|
|
|
71
72
|
* Unwrapping optional/nullable layers
|
|
72
73
|
* ```typescript
|
|
73
74
|
* const field = z.string().default('world').optional();
|
|
74
|
-
* const defaultValue =
|
|
75
|
+
* const defaultValue = extractDefaultValue(field);
|
|
75
76
|
* // Result: 'world' (unwraps optional to find default)
|
|
76
77
|
* ```
|
|
77
78
|
*
|
|
@@ -79,7 +80,7 @@ type Simplify<T> = {
|
|
|
79
80
|
* Union with only nullish types stripped to single type
|
|
80
81
|
* ```typescript
|
|
81
82
|
* const field = z.union([z.string().default('hello'), z.null()]);
|
|
82
|
-
* const defaultValue =
|
|
83
|
+
* const defaultValue = extractDefaultValue(field);
|
|
83
84
|
* // Result: 'hello' (null stripped, leaving only string)
|
|
84
85
|
* ```
|
|
85
86
|
*
|
|
@@ -87,7 +88,7 @@ type Simplify<T> = {
|
|
|
87
88
|
* Union with multiple non-nullish types
|
|
88
89
|
* ```typescript
|
|
89
90
|
* const field = z.union([z.string().default('hello'), z.number()]);
|
|
90
|
-
* const defaultValue =
|
|
91
|
+
* const defaultValue = extractDefaultValue(field);
|
|
91
92
|
* // Result: undefined (multiple non-nullish types - no default extracted)
|
|
92
93
|
* ```
|
|
93
94
|
*
|
|
@@ -95,7 +96,7 @@ type Simplify<T> = {
|
|
|
95
96
|
* Field without default
|
|
96
97
|
* ```typescript
|
|
97
98
|
* const field = z.string().optional();
|
|
98
|
-
* const defaultValue =
|
|
99
|
+
* const defaultValue = extractDefaultValue(field);
|
|
99
100
|
* // Result: undefined
|
|
100
101
|
* ```
|
|
101
102
|
*
|
|
@@ -103,7 +104,7 @@ type Simplify<T> = {
|
|
|
103
104
|
* @see {@link tryStripNullishOnly} for union nullish stripping logic
|
|
104
105
|
* @since 0.1.0
|
|
105
106
|
*/
|
|
106
|
-
declare function
|
|
107
|
+
declare function extractDefaultValue<T extends z.ZodType>(field: T): z.input<T> | undefined;
|
|
107
108
|
/**
|
|
108
109
|
* Extracts default values from a Zod object schema, returning only fields with explicit `.default()`.
|
|
109
110
|
*
|
|
@@ -173,15 +174,24 @@ declare function extractDefault<T extends z.ZodTypeAny>(field: T): z.infer<T> |
|
|
|
173
174
|
* <Input type="number" value={field.value ?? ''} />
|
|
174
175
|
* ```
|
|
175
176
|
*
|
|
176
|
-
* @see {@link
|
|
177
|
+
* @see {@link extractDefaultValue} for extracting defaults from individual fields
|
|
177
178
|
* @since 0.1.0
|
|
178
179
|
*/
|
|
179
|
-
declare function getSchemaDefaults<TSchema extends z.
|
|
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?: {
|
|
180
181
|
discriminator?: {
|
|
181
|
-
|
|
182
|
-
value:
|
|
182
|
+
key: TDiscriminatorKey;
|
|
183
|
+
value: TDiscriminatorValue;
|
|
183
184
|
};
|
|
184
|
-
}): Simplify<Partial<z.
|
|
185
|
+
}): Simplify<Partial<z.input<TSchema>>>;
|
|
186
|
+
|
|
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, }: {
|
|
188
|
+
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;
|
|
185
195
|
|
|
186
196
|
/**
|
|
187
197
|
* Type representing a Zod type that has an unwrap method
|
|
@@ -515,26 +525,70 @@ type ZodUnionCheck = $ZodCheckLessThanDef | $ZodCheckGreaterThanDef | $ZodCheckM
|
|
|
515
525
|
* @since 0.4.0
|
|
516
526
|
*/
|
|
517
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;
|
|
518
567
|
/**
|
|
519
568
|
* Extracts a specific schema option from a discriminated union based on the discriminator field value.
|
|
520
569
|
*
|
|
521
|
-
* This function finds and returns the matching schema
|
|
570
|
+
* This function finds and returns the **exact matching schema** from a `ZodDiscriminatedUnion` by
|
|
522
571
|
* comparing the discriminator field value. It's used internally by {@link getSchemaDefaults} to
|
|
523
572
|
* extract defaults from the correct schema variant in a discriminated union.
|
|
524
573
|
*
|
|
525
|
-
* **
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* 3. Returns the first matching schema option, or `undefined` if no match found
|
|
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.
|
|
529
577
|
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
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)
|
|
533
587
|
* @param params - Parameters object
|
|
534
588
|
* @param params.schema - The discriminated union schema to search
|
|
535
|
-
* @param params.
|
|
589
|
+
* @param params.discriminatorKey - The discriminator field name (e.g., "mode", "type")
|
|
536
590
|
* @param params.discriminatorValue - The discriminator value to match (e.g., "create", "edit")
|
|
537
|
-
* @returns The matching schema option, or `undefined` if not found
|
|
591
|
+
* @returns The exact matching schema option (with precise type), or `undefined` if not found
|
|
538
592
|
*
|
|
539
593
|
* @example
|
|
540
594
|
* Basic discriminated union - create/edit mode
|
|
@@ -555,7 +609,7 @@ declare function getFieldChecks<T extends z.ZodTypeAny>(field: T): Array<ZodUnio
|
|
|
555
609
|
* // Extract the "create" schema
|
|
556
610
|
* const createSchema = extractDiscriminatedSchema({
|
|
557
611
|
* schema: userSchema,
|
|
558
|
-
*
|
|
612
|
+
* discriminatorKey: 'mode',
|
|
559
613
|
* discriminatorValue: 'create',
|
|
560
614
|
* });
|
|
561
615
|
* // Result: z.object({ mode: z.literal('create'), name: z.string(), age: z.number().optional() })
|
|
@@ -563,7 +617,7 @@ declare function getFieldChecks<T extends z.ZodTypeAny>(field: T): Array<ZodUnio
|
|
|
563
617
|
* // Extract the "edit" schema
|
|
564
618
|
* const editSchema = extractDiscriminatedSchema({
|
|
565
619
|
* schema: userSchema,
|
|
566
|
-
*
|
|
620
|
+
* discriminatorKey: 'mode',
|
|
567
621
|
* discriminatorValue: 'edit',
|
|
568
622
|
* });
|
|
569
623
|
* // Result: z.object({ mode: z.literal('edit'), id: z.number(), name: z.string().optional() })
|
|
@@ -579,7 +633,7 @@ declare function getFieldChecks<T extends z.ZodTypeAny>(field: T): Array<ZodUnio
|
|
|
579
633
|
*
|
|
580
634
|
* const clickSchema = extractDiscriminatedSchema({
|
|
581
635
|
* schema: eventSchema,
|
|
582
|
-
*
|
|
636
|
+
* discriminatorKey: 'type',
|
|
583
637
|
* discriminatorValue: 'click',
|
|
584
638
|
* });
|
|
585
639
|
* // Result: z.object({ type: z.literal('click'), x: z.number(), y: z.number() })
|
|
@@ -594,19 +648,44 @@ declare function getFieldChecks<T extends z.ZodTypeAny>(field: T): Array<ZodUnio
|
|
|
594
648
|
*
|
|
595
649
|
* const result = extractDiscriminatedSchema({
|
|
596
650
|
* schema,
|
|
597
|
-
*
|
|
651
|
+
* discriminatorKey: 'mode',
|
|
598
652
|
* discriminatorValue: 'invalid', // doesn't match any option
|
|
599
653
|
* });
|
|
600
654
|
* // Result: undefined
|
|
601
655
|
* ```
|
|
602
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
|
+
*
|
|
603
681
|
* @see {@link getSchemaDefaults} for usage with discriminated unions
|
|
682
|
+
* @see {@link ExtractZodUnionMember} for the type-level extraction logic
|
|
604
683
|
* @since 0.6.0
|
|
605
684
|
*/
|
|
606
|
-
declare const extractDiscriminatedSchema: <TSchema extends z.
|
|
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, }: {
|
|
607
686
|
schema: TSchema;
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}) =>
|
|
687
|
+
key: TDiscriminatorKey;
|
|
688
|
+
value: TDiscriminatorValue;
|
|
689
|
+
}) => ExtractZodUnionMember<TSchema, TDiscriminatorKey, TDiscriminatorValue> | undefined;
|
|
611
690
|
|
|
612
|
-
export { type Simplify, type ZodUnionCheck, canUnwrap,
|
|
691
|
+
export { type Simplify, type ZodUnionCheck, canUnwrap, extractDefaultValue, extractDiscriminatedSchema, extractFieldFromSchema, getFieldChecks, getPrimitiveType, getSchemaDefaults, removeDefault, requiresValidInput, tryStripNullishOnly };
|