zod 3.11.6 โ 3.13.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 +104 -45
- package/lib/ZodError.d.ts +16 -5
- package/lib/ZodError.js +47 -42
- package/lib/benchmarks/discriminatedUnion.d.ts +5 -0
- package/lib/benchmarks/discriminatedUnion.js +79 -0
- package/lib/benchmarks/index.d.ts +0 -1
- package/lib/benchmarks/index.js +2 -2
- package/lib/benchmarks/object.d.ts +0 -1
- package/lib/benchmarks/object.js +3 -4
- package/lib/benchmarks/string.d.ts +0 -1
- package/lib/benchmarks/string.js +1 -2
- package/lib/benchmarks/union.d.ts +0 -1
- package/lib/benchmarks/union.js +2 -3
- package/lib/external.d.ts +1 -1
- package/lib/external.js +1 -1
- package/lib/helpers/errorUtil.d.ts +0 -1
- package/lib/helpers/errorUtil.js +0 -1
- package/lib/helpers/parseUtil.d.ts +1 -2
- package/lib/helpers/parseUtil.js +6 -5
- package/lib/helpers/partialUtil.d.ts +0 -1
- package/lib/helpers/partialUtil.js +0 -1
- package/lib/helpers/typeAliases.d.ts +2 -0
- package/lib/helpers/typeAliases.js +2 -0
- package/lib/helpers/util.d.ts +0 -1
- package/lib/helpers/util.js +0 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/index.mjs +3390 -2
- package/lib/types.d.ts +63 -10
- package/lib/types.js +191 -22
- package/package.json +5 -5
- package/lib/ZodError.d.ts.map +0 -1
- package/lib/ZodError.js.map +0 -1
- package/lib/benchmarks/index.d.ts.map +0 -1
- package/lib/benchmarks/index.js.map +0 -1
- package/lib/benchmarks/object.d.ts.map +0 -1
- package/lib/benchmarks/object.js.map +0 -1
- package/lib/benchmarks/string.d.ts.map +0 -1
- package/lib/benchmarks/string.js.map +0 -1
- package/lib/benchmarks/union.d.ts.map +0 -1
- package/lib/benchmarks/union.js.map +0 -1
- package/lib/external.d.ts.map +0 -1
- package/lib/external.js.map +0 -1
- package/lib/helpers/errorUtil.d.ts.map +0 -1
- package/lib/helpers/errorUtil.js.map +0 -1
- package/lib/helpers/parseUtil.d.ts.map +0 -1
- package/lib/helpers/parseUtil.js.map +0 -1
- package/lib/helpers/partialUtil.d.ts.map +0 -1
- package/lib/helpers/partialUtil.js.map +0 -1
- package/lib/helpers/util.d.ts.map +0 -1
- package/lib/helpers/util.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/index.mjs.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,21 +8,29 @@
|
|
|
8
8
|
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a>
|
|
10
10
|
<a href="./src/__tests__" rel="nofollow"><img src="./coverage.svg" alt="coverage"></a>
|
|
11
|
-
|
|
11
|
+
<a href="https://discord.gg/KaSRdyX2vc" rel="nofollow"><img src="https://img.shields.io/discord/893487829802418277?label=Discord&logo=discord&logoColor=white" alt="discord server"></a>
|
|
12
12
|
</p>
|
|
13
13
|
<p align="center">
|
|
14
|
-
by
|
|
14
|
+
by <a href="https://twitter.com/colinhacks">@colinhacks</a>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
|
-
> Hi! Colin here, creator of Zod. I hope you find it easy to use and powerful enough for all your use cases. If you have any issues or suggestions, please
|
|
17
|
+
> Hi! Colin here, creator of Zod. I hope you find it easy to use and powerful enough for all your use cases. If you have any issues or suggestions, please [open an issue](https://github.com/colinhacks/zod/issues/new)!
|
|
18
18
|
>
|
|
19
19
|
> If you like typesafety, check out my other library [tRPC](https://trpc.io). It works in concert with Zod to provide a seamless way to build end-to-end typesafe APIs without GraphQL or code generation โ just TypeScript.
|
|
20
20
|
>
|
|
21
21
|
> Colin (AKA [@colinhacks](https://twitter.com/colinhacks))
|
|
22
22
|
|
|
23
|
+
<h3 align="center">
|
|
24
|
+
<a href="https://discord.gg/RcG33DQJdf">๐ฌ Chat on Discord</a>
|
|
25
|
+
ยท
|
|
26
|
+
<a href="https://zod.js.org/">๐ Explore the Docs</a>
|
|
27
|
+
ยท
|
|
28
|
+
<a href="https://www.npmjs.com/package/zod">โจ Install Zod</a>
|
|
29
|
+
</h3>
|
|
30
|
+
|
|
23
31
|
<br/>
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
These docs have been translated into [Chinese](./README_ZH.md).
|
|
26
34
|
|
|
27
35
|
# Table of contents
|
|
28
36
|
|
|
@@ -36,9 +44,9 @@ This docs have been translated into [Chinese](./README_ZH.md).
|
|
|
36
44
|
- [Strings](#strings)
|
|
37
45
|
- [Numbers](#numbers)
|
|
38
46
|
- [Booleans](#booleans)
|
|
39
|
-
- [
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
- [Dates](#dates)
|
|
48
|
+
- [Zod enums](#zod-enums)
|
|
49
|
+
- [Native enums](#native-enums)
|
|
42
50
|
- [Optionals](#optionals)
|
|
43
51
|
- [Nullables](#nullables)
|
|
44
52
|
- [Objects](#objects)
|
|
@@ -53,6 +61,7 @@ This docs have been translated into [Chinese](./README_ZH.md).
|
|
|
53
61
|
- [.strip](#strip)
|
|
54
62
|
- [.catchall](#catchall)
|
|
55
63
|
- [Arrays](#arrays)
|
|
64
|
+
- [.element](#element)
|
|
56
65
|
- [.nonempty](#nonempty)
|
|
57
66
|
- [.min/.max/.length](#minmaxlength)
|
|
58
67
|
- [Tuples](#tuples)
|
|
@@ -60,6 +69,7 @@ This docs have been translated into [Chinese](./README_ZH.md).
|
|
|
60
69
|
- [Maps](#maps)
|
|
61
70
|
- [Sets](#sets)
|
|
62
71
|
- [Unions](#unions)
|
|
72
|
+
- [Discriminated Unions](#discriminated-unions)
|
|
63
73
|
- [Recursive types](#recursive-types)
|
|
64
74
|
- [JSON type](#json-type)
|
|
65
75
|
- [Cyclical data](#cyclical-objects)
|
|
@@ -105,7 +115,7 @@ Some other great aspects:
|
|
|
105
115
|
- Zero dependencies
|
|
106
116
|
- Works in Node.js and browsers (including IE 11)
|
|
107
117
|
- Tiny: 8kb minified + zipped
|
|
108
|
-
- Immutable: methods (i.e. `.optional()` return a new instance
|
|
118
|
+
- Immutable: methods (i.e. `.optional()`) return a new instance
|
|
109
119
|
- Concise, chainable interface
|
|
110
120
|
- Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
|
|
111
121
|
- Works with plain JavaScript too! You don't need to use TypeScript.
|
|
@@ -147,7 +157,7 @@ Sponsorship at any level is appreciated and encouraged. Zod is maintained by a s
|
|
|
147
157
|
<span>creator of <a href="https://blitzjs.com">Blitz.js</a></span>
|
|
148
158
|
<br />
|
|
149
159
|
</td>
|
|
150
|
-
|
|
160
|
+
|
|
151
161
|
</tr>
|
|
152
162
|
<tr>
|
|
153
163
|
<td align="center">
|
|
@@ -215,6 +225,7 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
215
225
|
|
|
216
226
|
- [`tRPC`](https://github.com/trpc/trpc): Build end-to-end typesafe APIs without GraphQL.
|
|
217
227
|
- [`ts-to-zod`](https://github.com/fabien0102/ts-to-zod): Convert TypeScript definitions into Zod schemas.
|
|
228
|
+
- [`zod-to-ts`](https://github.com/sachinraja/zod-to-ts): Generate TypeScript definitions from Zod schemas.
|
|
218
229
|
- [`@anatine/zod-openapi`](https://github.com/anatine/zod-plugins/tree/main/libs/zod-openapi): Converts a Zod schema to an OpenAPI v3.x `SchemaObject`.
|
|
219
230
|
- [`@anatine/zod-mock`](https://github.com/anatine/zod-plugins/tree/main/libs/zod-mock): Generate mock data from a Zod schema. Powered by [faker.js](https://github.com/Marak/Faker.js).
|
|
220
231
|
- [`@anatine/zod-nestjs`](https://github.com/anatine/zod-plugins/tree/main/libs/zod-nestjs): Helper methods for using Zod in a NestJS project.
|
|
@@ -223,13 +234,17 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
223
234
|
- [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
|
|
224
235
|
- [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares.
|
|
225
236
|
- [`zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema): Convert your Zod schemas into [JSON Schemas](https://json-schema.org/).
|
|
237
|
+
- [`json-schema-to-zod`](https://github.com/StefanTerdell/json-schema-to-zod): Convert your [JSON Schemas](https://json-schema.org/) into Zod schemas. Use it live [here](https://StefanTerdell.github.io/json-schema-to-zod-react/).
|
|
226
238
|
- [`json-to-zod`](https://github.com/rsinohara/json-to-zod): Convert JSON objects into Zod schemas. Use it live [here](https://rsinohara.github.io/json-to-zod-react/).
|
|
227
239
|
- [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema.
|
|
240
|
+
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
241
|
+
- [`graphql-codegen-typescript-validation-schema`](https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema): GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema
|
|
242
|
+
- [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema.
|
|
228
243
|
|
|
229
244
|
### Form integrations
|
|
230
245
|
|
|
231
246
|
- [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form
|
|
232
|
-
- [`formik`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod
|
|
247
|
+
- [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod
|
|
233
248
|
|
|
234
249
|
# Basic usage
|
|
235
250
|
|
|
@@ -310,15 +325,6 @@ tuna.value; // "tuna"
|
|
|
310
325
|
|
|
311
326
|
## Strings
|
|
312
327
|
|
|
313
|
-
You can customize certain errors when creating a string schema.
|
|
314
|
-
|
|
315
|
-
```ts
|
|
316
|
-
const name = z.string({
|
|
317
|
-
required: "Name is required",
|
|
318
|
-
invalid: "Invalid name",
|
|
319
|
-
});
|
|
320
|
-
```
|
|
321
|
-
|
|
322
328
|
Zod includes a handful of string-specific validations.
|
|
323
329
|
|
|
324
330
|
```ts
|
|
@@ -408,11 +414,30 @@ const isActive = z.boolean({
|
|
|
408
414
|
});
|
|
409
415
|
```
|
|
410
416
|
|
|
411
|
-
##
|
|
417
|
+
## Dates
|
|
418
|
+
z.date() accepts a date, not a date string
|
|
419
|
+
```ts
|
|
420
|
+
z.date().safeParse( new Date() ) // success: true
|
|
421
|
+
z.date().safeParse( '2022-01-12T00:00:00.000Z' ) // success: false
|
|
422
|
+
```
|
|
412
423
|
|
|
413
|
-
|
|
424
|
+
To allow for dates or date strings, you can use preprocess
|
|
425
|
+
```ts
|
|
426
|
+
const dateSchema = z.preprocess(
|
|
427
|
+
arg => {
|
|
428
|
+
if ( typeof arg == 'string' || arg instanceof Date )
|
|
429
|
+
return new Date( arg )
|
|
430
|
+
},
|
|
431
|
+
z.date()
|
|
432
|
+
)
|
|
433
|
+
type DateSchema = z.infer<typeof dateSchema>
|
|
434
|
+
// type DateSchema = Date
|
|
414
435
|
|
|
415
|
-
|
|
436
|
+
dateSchema.safeParse( new Date( '1/12/22' ) ) // success: true
|
|
437
|
+
dateSchema.safeParse( '2022-01-12T00:00:00.000Z' ) // success: true
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Zod enums
|
|
416
441
|
|
|
417
442
|
```ts
|
|
418
443
|
const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]);
|
|
@@ -420,22 +445,20 @@ type FishEnum = z.infer<typeof FishEnum>;
|
|
|
420
445
|
// 'Salmon' | 'Tuna' | 'Trout'
|
|
421
446
|
```
|
|
422
447
|
|
|
423
|
-
|
|
448
|
+
`z.enum` is a Zod-native way to declare a schema with a fixed set of allowable _string_ values. Pass the array of values directly into `z.enum()`. Alternatively, use `as const` to define your enum values as a tuple of strings. See the [const assertion docs](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) for details.
|
|
424
449
|
|
|
425
450
|
```ts
|
|
426
451
|
const VALUES = ["Salmon", "Tuna", "Trout"] as const;
|
|
427
452
|
const FishEnum = z.enum(VALUES);
|
|
428
453
|
```
|
|
429
454
|
|
|
430
|
-
This is not allowed
|
|
455
|
+
This is not allowed, since Zod isn't able to infer the exact values of each elements.
|
|
431
456
|
|
|
432
457
|
```ts
|
|
433
458
|
const fish = ["Salmon", "Tuna", "Trout"];
|
|
434
459
|
const FishEnum = z.enum(fish);
|
|
435
460
|
```
|
|
436
461
|
|
|
437
|
-
In that case, the inferred type of `fish` is simply `string[]`, so Zod isn't able to infer the individual enum elements.
|
|
438
|
-
|
|
439
462
|
**Autocompletion**
|
|
440
463
|
|
|
441
464
|
To get autocompletion with a Zod enum, use the `.enum` property of your schema:
|
|
@@ -444,12 +467,12 @@ To get autocompletion with a Zod enum, use the `.enum` property of your schema:
|
|
|
444
467
|
FishEnum.enum.Salmon; // => autocompletes
|
|
445
468
|
|
|
446
469
|
FishEnum.enum;
|
|
447
|
-
/*
|
|
470
|
+
/*
|
|
448
471
|
=> {
|
|
449
472
|
Salmon: "Salmon",
|
|
450
473
|
Tuna: "Tuna",
|
|
451
474
|
Trout: "Trout",
|
|
452
|
-
}
|
|
475
|
+
}
|
|
453
476
|
*/
|
|
454
477
|
```
|
|
455
478
|
|
|
@@ -459,7 +482,7 @@ You can also retrieve the list of options as a tuple with the `.options` propert
|
|
|
459
482
|
FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
|
|
460
483
|
```
|
|
461
484
|
|
|
462
|
-
|
|
485
|
+
## Native enums
|
|
463
486
|
|
|
464
487
|
Zod enums are the recommended approach to defining and validating enums. But if you need to validate against an enum from a third-party library (or you don't want to rewrite your existing enums) you can use `z.nativeEnum()` .
|
|
465
488
|
|
|
@@ -684,11 +707,11 @@ You can also specify which properties to make optional:
|
|
|
684
707
|
const optionalEmail = user.partial({
|
|
685
708
|
email: true,
|
|
686
709
|
});
|
|
687
|
-
/*
|
|
688
|
-
{
|
|
689
|
-
email?: string | undefined;
|
|
710
|
+
/*
|
|
711
|
+
{
|
|
712
|
+
email?: string | undefined;
|
|
690
713
|
username: string
|
|
691
|
-
}
|
|
714
|
+
}
|
|
692
715
|
*/
|
|
693
716
|
```
|
|
694
717
|
|
|
@@ -708,9 +731,9 @@ const user = z.object({
|
|
|
708
731
|
|
|
709
732
|
const deepPartialUser = user.deepPartial();
|
|
710
733
|
|
|
711
|
-
/*
|
|
734
|
+
/*
|
|
712
735
|
{
|
|
713
|
-
username?: string | undefined,
|
|
736
|
+
username?: string | undefined,
|
|
714
737
|
location?: {
|
|
715
738
|
latitude?: number | undefined;
|
|
716
739
|
longitude?: number | undefined;
|
|
@@ -814,6 +837,14 @@ z.string().optional().array(); // (string | undefined)[]
|
|
|
814
837
|
z.string().array().optional(); // string[] | undefined
|
|
815
838
|
```
|
|
816
839
|
|
|
840
|
+
### `.element`
|
|
841
|
+
|
|
842
|
+
Use `.element` to access the schema for an element of the array.
|
|
843
|
+
|
|
844
|
+
```ts
|
|
845
|
+
stringArray.element; // => string schema
|
|
846
|
+
```
|
|
847
|
+
|
|
817
848
|
### `.nonempty`
|
|
818
849
|
|
|
819
850
|
If you want to ensure that an array contains at least one element, use `.nonempty()`.
|
|
@@ -882,6 +913,25 @@ For convenience, you can also use the `.or` method:
|
|
|
882
913
|
const stringOrNumber = z.string().or(z.number());
|
|
883
914
|
```
|
|
884
915
|
|
|
916
|
+
### Discriminated unions
|
|
917
|
+
|
|
918
|
+
If the union consists of object schemas all identifiable by a common property, it is possible to use
|
|
919
|
+
the `z.discriminatedUnion` method.
|
|
920
|
+
|
|
921
|
+
The advantage is in more efficient evaluation and more human friendly errors. With the basic union method the input is
|
|
922
|
+
tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in
|
|
923
|
+
the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing
|
|
924
|
+
against it, and showing only the issues related to this "option".
|
|
925
|
+
|
|
926
|
+
```ts
|
|
927
|
+
const item = z
|
|
928
|
+
.discriminatedUnion("type", [
|
|
929
|
+
z.object({ type: z.literal("a"), a: z.string() }),
|
|
930
|
+
z.object({ type: z.literal("b"), b: z.string() }),
|
|
931
|
+
])
|
|
932
|
+
.parse({ type: "a", a: "abc" });
|
|
933
|
+
```
|
|
934
|
+
|
|
885
935
|
## Records
|
|
886
936
|
|
|
887
937
|
Record schemas are used to validate types such as `{ [k: string]: number }`.
|
|
@@ -936,15 +986,24 @@ Since Zod is trying to bridge the gap between static and runtime types, it doesn
|
|
|
936
986
|
const stringNumberMap = z.map(z.string(), z.number());
|
|
937
987
|
|
|
938
988
|
type StringNumberMap = z.infer<typeof stringNumberMap>;
|
|
939
|
-
// type
|
|
989
|
+
// type StringNumberMap = Map<string, number>
|
|
940
990
|
```
|
|
941
991
|
|
|
942
992
|
## Sets
|
|
943
993
|
|
|
944
994
|
```ts
|
|
945
|
-
const numberSet = z.set(z.
|
|
946
|
-
type
|
|
947
|
-
// Set<number>
|
|
995
|
+
const numberSet = z.set(z.number());
|
|
996
|
+
type NumberSet = z.infer<typeof numberSet>;
|
|
997
|
+
// type NumberSet = Set<number>
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
### `.nonempty/.min/.max/.size`
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
z.set(z.string()).nonempty(); // must contain at least one item
|
|
1004
|
+
z.set(z.string()).min(5); // must contain 5 or more items
|
|
1005
|
+
z.set(z.string()).max(5); // must contain 5 or fewer items
|
|
1006
|
+
z.set(z.string()).size(5); // must contain 5 items exactly
|
|
948
1007
|
```
|
|
949
1008
|
|
|
950
1009
|
## Intersections
|
|
@@ -1007,8 +1066,8 @@ interface Category {
|
|
|
1007
1066
|
subcategories: Category[];
|
|
1008
1067
|
}
|
|
1009
1068
|
|
|
1010
|
-
// cast to z.
|
|
1011
|
-
const Category: z.
|
|
1069
|
+
// cast to z.ZodType<Category>
|
|
1070
|
+
const Category: z.ZodType<Category> = z.lazy(() =>
|
|
1012
1071
|
z.object({
|
|
1013
1072
|
name: z.string(),
|
|
1014
1073
|
subcategories: z.array(Category),
|
|
@@ -1045,7 +1104,7 @@ interface Category extends z.infer<typeof BaseCategory> {
|
|
|
1045
1104
|
|
|
1046
1105
|
// merge the base schema with
|
|
1047
1106
|
// a new Zod schema containing relations
|
|
1048
|
-
const Category: z.
|
|
1107
|
+
const Category: z.ZodType<Category> = BaseCategory.merge(
|
|
1049
1108
|
z.object({
|
|
1050
1109
|
subcategories: z.lazy(() => z.array(Category)),
|
|
1051
1110
|
})
|
|
@@ -1060,7 +1119,7 @@ If you want to validate any JSON value, you can use the snippet below.
|
|
|
1060
1119
|
type Literal = boolean | null | number | string;
|
|
1061
1120
|
type Json = Literal | { [key: string]: Json } | Json[];
|
|
1062
1121
|
const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
1063
|
-
const jsonSchema: z.
|
|
1122
|
+
const jsonSchema: z.ZodType<Json> = z.lazy(() =>
|
|
1064
1123
|
z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)])
|
|
1065
1124
|
);
|
|
1066
1125
|
|
|
@@ -1071,7 +1130,7 @@ Thanks to [ggoodman](https://github.com/ggoodman) for suggesting this.
|
|
|
1071
1130
|
|
|
1072
1131
|
#### Cyclical objects
|
|
1073
1132
|
|
|
1074
|
-
Despite supporting recursive schemas, passing
|
|
1133
|
+
Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop.
|
|
1075
1134
|
|
|
1076
1135
|
## Promises
|
|
1077
1136
|
|
|
@@ -1607,7 +1666,7 @@ A convenience method for creating intersection types.
|
|
|
1607
1666
|
z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: string } & { age: number }
|
|
1608
1667
|
|
|
1609
1668
|
// equivalent to
|
|
1610
|
-
z.intersection(z.string(), z.number());
|
|
1669
|
+
z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
|
1611
1670
|
```
|
|
1612
1671
|
|
|
1613
1672
|
# Type inference
|
package/lib/ZodError.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ZodParsedType } from "./helpers/parseUtil";
|
|
2
|
+
import { Primitive } from "./helpers/typeAliases";
|
|
2
3
|
import { util } from "./helpers/util";
|
|
3
4
|
export declare const ZodIssueCode: {
|
|
4
5
|
invalid_type: "invalid_type";
|
|
5
6
|
custom: "custom";
|
|
6
7
|
invalid_union: "invalid_union";
|
|
8
|
+
invalid_union_discriminator: "invalid_union_discriminator";
|
|
7
9
|
invalid_enum_value: "invalid_enum_value";
|
|
8
10
|
unrecognized_keys: "unrecognized_keys";
|
|
9
11
|
invalid_arguments: "invalid_arguments";
|
|
@@ -33,6 +35,10 @@ export interface ZodInvalidUnionIssue extends ZodIssueBase {
|
|
|
33
35
|
code: typeof ZodIssueCode.invalid_union;
|
|
34
36
|
unionErrors: ZodError[];
|
|
35
37
|
}
|
|
38
|
+
export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase {
|
|
39
|
+
code: typeof ZodIssueCode.invalid_union_discriminator;
|
|
40
|
+
options: Primitive[];
|
|
41
|
+
}
|
|
36
42
|
export interface ZodInvalidEnumValueIssue extends ZodIssueBase {
|
|
37
43
|
code: typeof ZodIssueCode.invalid_enum_value;
|
|
38
44
|
options: (string | number)[];
|
|
@@ -57,13 +63,13 @@ export interface ZodTooSmallIssue extends ZodIssueBase {
|
|
|
57
63
|
code: typeof ZodIssueCode.too_small;
|
|
58
64
|
minimum: number;
|
|
59
65
|
inclusive: boolean;
|
|
60
|
-
type: "array" | "string" | "number";
|
|
66
|
+
type: "array" | "string" | "number" | "set";
|
|
61
67
|
}
|
|
62
68
|
export interface ZodTooBigIssue extends ZodIssueBase {
|
|
63
69
|
code: typeof ZodIssueCode.too_big;
|
|
64
70
|
maximum: number;
|
|
65
71
|
inclusive: boolean;
|
|
66
|
-
type: "array" | "string" | "number";
|
|
72
|
+
type: "array" | "string" | "number" | "set";
|
|
67
73
|
}
|
|
68
74
|
export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase {
|
|
69
75
|
code: typeof ZodIssueCode.invalid_intersection_types;
|
|
@@ -81,7 +87,7 @@ export interface ZodCustomIssue extends ZodIssueBase {
|
|
|
81
87
|
export declare type DenormalizedError = {
|
|
82
88
|
[k: string]: DenormalizedError | string[];
|
|
83
89
|
};
|
|
84
|
-
export declare type ZodIssueOptionalMessage = ZodInvalidTypeIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodCustomIssue;
|
|
90
|
+
export declare type ZodIssueOptionalMessage = ZodInvalidTypeIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidUnionDiscriminatorIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodCustomIssue;
|
|
85
91
|
export declare type ZodIssue = ZodIssueOptionalMessage & {
|
|
86
92
|
message: string;
|
|
87
93
|
};
|
|
@@ -104,7 +110,13 @@ export declare class ZodError<T = any> extends Error {
|
|
|
104
110
|
get isEmpty(): boolean;
|
|
105
111
|
addIssue: (sub: ZodIssue) => void;
|
|
106
112
|
addIssues: (subs?: ZodIssue[]) => void;
|
|
107
|
-
flatten
|
|
113
|
+
flatten(mapper?: (issue: ZodIssue) => string): {
|
|
114
|
+
formErrors: string[];
|
|
115
|
+
fieldErrors: {
|
|
116
|
+
[k: string]: string[];
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
flatten<U>(mapper?: (issue: ZodIssue) => U): {
|
|
108
120
|
formErrors: U[];
|
|
109
121
|
fieldErrors: {
|
|
110
122
|
[k: string]: U[];
|
|
@@ -136,4 +148,3 @@ export declare let overrideErrorMap: (issue: ZodIssueOptionalMessage, _ctx: Erro
|
|
|
136
148
|
};
|
|
137
149
|
export declare const setErrorMap: (map: ZodErrorMap) => void;
|
|
138
150
|
export {};
|
|
139
|
-
//# sourceMappingURL=ZodError.d.ts.map
|
package/lib/ZodError.js
CHANGED
|
@@ -57,6 +57,7 @@ exports.ZodIssueCode = util_1.util.arrayToEnum([
|
|
|
57
57
|
"invalid_type",
|
|
58
58
|
"custom",
|
|
59
59
|
"invalid_union",
|
|
60
|
+
"invalid_union_discriminator",
|
|
60
61
|
"invalid_enum_value",
|
|
61
62
|
"unrecognized_keys",
|
|
62
63
|
"invalid_arguments",
|
|
@@ -142,32 +143,6 @@ var ZodError = /** @class */ (function (_super) {
|
|
|
142
143
|
if (subs === void 0) { subs = []; }
|
|
143
144
|
_this.issues = __spreadArray(__spreadArray([], __read(_this.issues), false), __read(subs), false);
|
|
144
145
|
};
|
|
145
|
-
_this.flatten = function (mapper) {
|
|
146
|
-
var e_2, _a;
|
|
147
|
-
if (mapper === void 0) { mapper = function (issue) { return issue.message; }; }
|
|
148
|
-
var fieldErrors = {};
|
|
149
|
-
var formErrors = [];
|
|
150
|
-
try {
|
|
151
|
-
for (var _b = __values(_this.issues), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
152
|
-
var sub = _c.value;
|
|
153
|
-
if (sub.path.length > 0) {
|
|
154
|
-
fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
|
|
155
|
-
fieldErrors[sub.path[0]].push(mapper(sub));
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
formErrors.push(mapper(sub));
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
163
|
-
finally {
|
|
164
|
-
try {
|
|
165
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
166
|
-
}
|
|
167
|
-
finally { if (e_2) throw e_2.error; }
|
|
168
|
-
}
|
|
169
|
-
return { formErrors: formErrors, fieldErrors: fieldErrors };
|
|
170
|
-
};
|
|
171
146
|
var actualProto = _newTarget.prototype;
|
|
172
147
|
if (Object.setPrototypeOf) {
|
|
173
148
|
// eslint-disable-next-line ban/ban
|
|
@@ -204,6 +179,32 @@ var ZodError = /** @class */ (function (_super) {
|
|
|
204
179
|
enumerable: false,
|
|
205
180
|
configurable: true
|
|
206
181
|
});
|
|
182
|
+
ZodError.prototype.flatten = function (mapper) {
|
|
183
|
+
var e_2, _a;
|
|
184
|
+
if (mapper === void 0) { mapper = function (issue) { return issue.message; }; }
|
|
185
|
+
var fieldErrors = {};
|
|
186
|
+
var formErrors = [];
|
|
187
|
+
try {
|
|
188
|
+
for (var _b = __values(this.issues), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
189
|
+
var sub = _c.value;
|
|
190
|
+
if (sub.path.length > 0) {
|
|
191
|
+
fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
|
|
192
|
+
fieldErrors[sub.path[0]].push(mapper(sub));
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
formErrors.push(mapper(sub));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
200
|
+
finally {
|
|
201
|
+
try {
|
|
202
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
203
|
+
}
|
|
204
|
+
finally { if (e_2) throw e_2.error; }
|
|
205
|
+
}
|
|
206
|
+
return { formErrors: formErrors, fieldErrors: fieldErrors };
|
|
207
|
+
};
|
|
207
208
|
Object.defineProperty(ZodError.prototype, "formErrors", {
|
|
208
209
|
get: function () {
|
|
209
210
|
return this.flatten();
|
|
@@ -226,21 +227,26 @@ var defaultErrorMap = function (issue, _ctx) {
|
|
|
226
227
|
message = "Required";
|
|
227
228
|
}
|
|
228
229
|
else {
|
|
229
|
-
message = "Expected "
|
|
230
|
+
message = "Expected ".concat(issue.expected, ", received ").concat(issue.received);
|
|
230
231
|
}
|
|
231
232
|
break;
|
|
232
233
|
case exports.ZodIssueCode.unrecognized_keys:
|
|
233
|
-
message = "Unrecognized key(s) in object: "
|
|
234
|
-
.map(function (k) { return "'"
|
|
235
|
-
.join(", ");
|
|
234
|
+
message = "Unrecognized key(s) in object: ".concat(issue.keys
|
|
235
|
+
.map(function (k) { return "'".concat(k, "'"); })
|
|
236
|
+
.join(", "));
|
|
236
237
|
break;
|
|
237
238
|
case exports.ZodIssueCode.invalid_union:
|
|
238
239
|
message = "Invalid input";
|
|
239
240
|
break;
|
|
241
|
+
case exports.ZodIssueCode.invalid_union_discriminator:
|
|
242
|
+
message = "Invalid discriminator value. Expected ".concat(issue.options
|
|
243
|
+
.map(function (val) { return (typeof val === "string" ? "'".concat(val, "'") : val); })
|
|
244
|
+
.join(" | "));
|
|
245
|
+
break;
|
|
240
246
|
case exports.ZodIssueCode.invalid_enum_value:
|
|
241
|
-
message = "Invalid enum value. Expected "
|
|
242
|
-
.map(function (val) { return (typeof val === "string" ? "'"
|
|
243
|
-
.join(" | ")
|
|
247
|
+
message = "Invalid enum value. Expected ".concat(issue.options
|
|
248
|
+
.map(function (val) { return (typeof val === "string" ? "'".concat(val, "'") : val); })
|
|
249
|
+
.join(" | "));
|
|
244
250
|
break;
|
|
245
251
|
case exports.ZodIssueCode.invalid_arguments:
|
|
246
252
|
message = "Invalid function arguments";
|
|
@@ -253,27 +259,27 @@ var defaultErrorMap = function (issue, _ctx) {
|
|
|
253
259
|
break;
|
|
254
260
|
case exports.ZodIssueCode.invalid_string:
|
|
255
261
|
if (issue.validation !== "regex")
|
|
256
|
-
message = "Invalid "
|
|
262
|
+
message = "Invalid ".concat(issue.validation);
|
|
257
263
|
else
|
|
258
264
|
message = "Invalid";
|
|
259
265
|
break;
|
|
260
266
|
case exports.ZodIssueCode.too_small:
|
|
261
267
|
if (issue.type === "array")
|
|
262
|
-
message = "
|
|
268
|
+
message = "Array must contain ".concat(issue.inclusive ? "at least" : "more than", " ").concat(issue.minimum, " element(s)");
|
|
263
269
|
else if (issue.type === "string")
|
|
264
|
-
message = "
|
|
270
|
+
message = "String must contain ".concat(issue.inclusive ? "at least" : "over", " ").concat(issue.minimum, " character(s)");
|
|
265
271
|
else if (issue.type === "number")
|
|
266
|
-
message = "
|
|
272
|
+
message = "Number must be greater than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.minimum);
|
|
267
273
|
else
|
|
268
274
|
message = "Invalid input";
|
|
269
275
|
break;
|
|
270
276
|
case exports.ZodIssueCode.too_big:
|
|
271
277
|
if (issue.type === "array")
|
|
272
|
-
message = "
|
|
278
|
+
message = "Array must contain ".concat(issue.inclusive ? "at most" : "less than", " ").concat(issue.maximum, " element(s)");
|
|
273
279
|
else if (issue.type === "string")
|
|
274
|
-
message = "
|
|
280
|
+
message = "String must contain ".concat(issue.inclusive ? "at most" : "under", " ").concat(issue.maximum, " character(s)");
|
|
275
281
|
else if (issue.type === "number")
|
|
276
|
-
message = "
|
|
282
|
+
message = "Number must be less than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.maximum);
|
|
277
283
|
else
|
|
278
284
|
message = "Invalid input";
|
|
279
285
|
break;
|
|
@@ -284,7 +290,7 @@ var defaultErrorMap = function (issue, _ctx) {
|
|
|
284
290
|
message = "Intersection results could not be merged";
|
|
285
291
|
break;
|
|
286
292
|
case exports.ZodIssueCode.not_multiple_of:
|
|
287
|
-
message = "
|
|
293
|
+
message = "Number must be a multiple of ".concat(issue.multipleOf);
|
|
288
294
|
break;
|
|
289
295
|
default:
|
|
290
296
|
message = _ctx.defaultError;
|
|
@@ -298,4 +304,3 @@ var setErrorMap = function (map) {
|
|
|
298
304
|
exports.overrideErrorMap = map;
|
|
299
305
|
};
|
|
300
306
|
exports.setErrorMap = setErrorMap;
|
|
301
|
-
//# sourceMappingURL=ZodError.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
var benchmark_1 = __importDefault(require("benchmark"));
|
|
7
|
+
var index_1 = require("../index");
|
|
8
|
+
var doubleSuite = new benchmark_1.default.Suite("z.discriminatedUnion: double");
|
|
9
|
+
var manySuite = new benchmark_1.default.Suite("z.discriminatedUnion: many");
|
|
10
|
+
var aSchema = index_1.z.object({
|
|
11
|
+
type: index_1.z.literal("a"),
|
|
12
|
+
});
|
|
13
|
+
var objA = {
|
|
14
|
+
type: "a",
|
|
15
|
+
};
|
|
16
|
+
var bSchema = index_1.z.object({
|
|
17
|
+
type: index_1.z.literal("b"),
|
|
18
|
+
});
|
|
19
|
+
var objB = {
|
|
20
|
+
type: "b",
|
|
21
|
+
};
|
|
22
|
+
var cSchema = index_1.z.object({
|
|
23
|
+
type: index_1.z.literal("c"),
|
|
24
|
+
});
|
|
25
|
+
var objC = {
|
|
26
|
+
type: "c",
|
|
27
|
+
};
|
|
28
|
+
var dSchema = index_1.z.object({
|
|
29
|
+
type: index_1.z.literal("d"),
|
|
30
|
+
});
|
|
31
|
+
var double = index_1.z.discriminatedUnion("type", [aSchema, bSchema]);
|
|
32
|
+
var many = index_1.z.discriminatedUnion("type", [aSchema, bSchema, cSchema, dSchema]);
|
|
33
|
+
doubleSuite
|
|
34
|
+
.add("valid: a", function () {
|
|
35
|
+
double.parse(objA);
|
|
36
|
+
})
|
|
37
|
+
.add("valid: b", function () {
|
|
38
|
+
double.parse(objB);
|
|
39
|
+
})
|
|
40
|
+
.add("invalid: null", function () {
|
|
41
|
+
try {
|
|
42
|
+
double.parse(null);
|
|
43
|
+
}
|
|
44
|
+
catch (err) { }
|
|
45
|
+
})
|
|
46
|
+
.add("invalid: wrong shape", function () {
|
|
47
|
+
try {
|
|
48
|
+
double.parse(objC);
|
|
49
|
+
}
|
|
50
|
+
catch (err) { }
|
|
51
|
+
})
|
|
52
|
+
.on("cycle", function (e) {
|
|
53
|
+
console.log("".concat(doubleSuite.name, ": ").concat(e.target));
|
|
54
|
+
});
|
|
55
|
+
manySuite
|
|
56
|
+
.add("valid: a", function () {
|
|
57
|
+
many.parse(objA);
|
|
58
|
+
})
|
|
59
|
+
.add("valid: c", function () {
|
|
60
|
+
many.parse(objC);
|
|
61
|
+
})
|
|
62
|
+
.add("invalid: null", function () {
|
|
63
|
+
try {
|
|
64
|
+
many.parse(null);
|
|
65
|
+
}
|
|
66
|
+
catch (err) { }
|
|
67
|
+
})
|
|
68
|
+
.add("invalid: wrong shape", function () {
|
|
69
|
+
try {
|
|
70
|
+
many.parse({ type: "unknown" });
|
|
71
|
+
}
|
|
72
|
+
catch (err) { }
|
|
73
|
+
})
|
|
74
|
+
.on("cycle", function (e) {
|
|
75
|
+
console.log("".concat(manySuite.name, ": ").concat(e.target));
|
|
76
|
+
});
|
|
77
|
+
exports.default = {
|
|
78
|
+
suites: [doubleSuite, manySuite],
|
|
79
|
+
};
|