zod 3.15.0 → 3.16.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.
- package/README.md +201 -164
- package/lib/ZodError.d.ts +4 -1
- package/lib/ZodError.js +13 -18
- package/lib/helpers/util.d.ts +1 -0
- package/lib/helpers/util.js +6 -0
- package/lib/index.mjs +57 -27
- package/lib/index.umd.js +57 -27
- package/lib/types.d.ts +14 -14
- package/lib/types.js +39 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="logo.svg" width="200px" align="center" />
|
|
2
|
+
<img src="logo.svg" width="200px" align="center" alt="Zod logo" />
|
|
3
3
|
<h1 align="center">Zod</h1>
|
|
4
|
+
<p align="center">
|
|
5
|
+
✨ <a href="https://zod.dev">https://zod.dev</a> ✨
|
|
6
|
+
<br/>
|
|
7
|
+
TypeScript-first schema validation with static type inference
|
|
8
|
+
</p>
|
|
4
9
|
</p>
|
|
10
|
+
<br/>
|
|
5
11
|
<p align="center">
|
|
6
12
|
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amaster"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Zod CI status" /></a>
|
|
7
13
|
<a href="https://twitter.com/colinhacks" rel="nofollow"><img src="https://img.shields.io/badge/created%20by-@colinhacks-4BBAAB.svg" alt="Created by Colin McDonnell"></a>
|
|
@@ -12,6 +18,8 @@
|
|
|
12
18
|
</p>
|
|
13
19
|
|
|
14
20
|
<div align="center">
|
|
21
|
+
<a href="https://zod.dev">Documentation</a>
|
|
22
|
+
<span> • </span>
|
|
15
23
|
<a href="https://discord.gg/RcG33DQJdf">Discord</a>
|
|
16
24
|
<span> • </span>
|
|
17
25
|
<a href="https://www.npmjs.com/package/zod">NPM</a>
|
|
@@ -24,61 +32,62 @@
|
|
|
24
32
|
<br />
|
|
25
33
|
</div>
|
|
26
34
|
|
|
35
|
+
<br/>
|
|
27
36
|
<br/>
|
|
28
37
|
|
|
29
|
-
These docs have been translated into [Chinese](./README_ZH.md).
|
|
38
|
+
> These docs have been translated into [Chinese](./README_ZH.md).
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
## Table of contents
|
|
32
41
|
|
|
33
42
|
<!-- The full documentation is available both on the [official documentation site](https://zod.js.org/) (recommended) and in `README.md`.
|
|
34
43
|
|
|
35
|
-
|
|
44
|
+
#### Go to [zod.js.org](https://zod.js.org) >> -->
|
|
36
45
|
|
|
37
|
-
- [
|
|
46
|
+
- [Introduction](#introduction)
|
|
47
|
+
- [Sponsors](#sponsors)
|
|
48
|
+
- [Ecosystem](#ecosystem)
|
|
38
49
|
- [Installation](#installation)
|
|
39
|
-
- [Ecosystem](#ecosystem)
|
|
40
50
|
- [Basic usage](#basic-usage)
|
|
41
|
-
- [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- [
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- [
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- [Schema methods](#zodtype-methods-and-properties)
|
|
51
|
+
- [Primitives](#primitives)
|
|
52
|
+
- [Literals](#literals)
|
|
53
|
+
- [Strings](#strings)
|
|
54
|
+
- [Numbers](#numbers)
|
|
55
|
+
- [NaNs](#nans)
|
|
56
|
+
- [Booleans](#booleans)
|
|
57
|
+
- [Dates](#dates)
|
|
58
|
+
- [Zod enums](#zod-enums)
|
|
59
|
+
- [Native enums](#native-enums)
|
|
60
|
+
- [Optionals](#optionals)
|
|
61
|
+
- [Nullables](#nullables)
|
|
62
|
+
- [Objects](#objects)
|
|
63
|
+
- [.shape](#shape)
|
|
64
|
+
- [.extend](#extend)
|
|
65
|
+
- [.merge](#merge)
|
|
66
|
+
- [.pick/.omit](#pickomit)
|
|
67
|
+
- [.partial](#partial)
|
|
68
|
+
- [.deepPartial](#deepPartial)
|
|
69
|
+
- [.passthrough](#passthrough)
|
|
70
|
+
- [.strict](#strict)
|
|
71
|
+
- [.strip](#strip)
|
|
72
|
+
- [.catchall](#catchall)
|
|
73
|
+
- [Arrays](#arrays)
|
|
74
|
+
- [.element](#element)
|
|
75
|
+
- [.nonempty](#nonempty)
|
|
76
|
+
- [.min/.max/.length](#minmaxlength)
|
|
77
|
+
- [Tuples](#tuples)
|
|
78
|
+
- [Unions](#unions)
|
|
79
|
+
- [Discriminated Unions](#discriminated-unions)
|
|
80
|
+
- [Records](#records)
|
|
81
|
+
- [Maps](#maps)
|
|
82
|
+
- [Sets](#sets)
|
|
83
|
+
- [Recursive types](#recursive-types)
|
|
84
|
+
- [JSON type](#json-type)
|
|
85
|
+
- [Cyclical data](#cyclical-objects)
|
|
86
|
+
- [Promises](#promises)
|
|
87
|
+
- [Instanceof](#instanceof)
|
|
88
|
+
- [Function schemas](#function-schemas)
|
|
89
|
+
- [Preprocess](#preprocess)
|
|
90
|
+
- [Schema methods](#schema-methods)
|
|
82
91
|
- [.parse](#parse)
|
|
83
92
|
- [.parseAsync](#parseasync)
|
|
84
93
|
- [.safeParse](#safeparse)
|
|
@@ -98,6 +107,7 @@ These docs have been translated into [Chinese](./README_ZH.md).
|
|
|
98
107
|
- [Type inference](#type-inference)
|
|
99
108
|
- [Writing generic functions](#writing-generic-functions)
|
|
100
109
|
- [Error handling](#error-handling)
|
|
110
|
+
- [Error formatting](#error-formatting)
|
|
101
111
|
- [Comparison](#comparison)
|
|
102
112
|
- [Joi](#joi)
|
|
103
113
|
- [Yup](#yup)
|
|
@@ -107,7 +117,7 @@ These docs have been translated into [Chinese](./README_ZH.md).
|
|
|
107
117
|
|
|
108
118
|
<!-- **Zod 2 is coming! Follow [@colinhacks](https://twitter.com/colinhacks) to stay updated and discuss the future of Zod.** -->
|
|
109
119
|
|
|
110
|
-
|
|
120
|
+
## Introduction
|
|
111
121
|
|
|
112
122
|
Zod is a TypeScript-first schema declaration and validation library. I'm using the term "schema" to broadly refer to any data type, from a simple `string` to a complex nested object.
|
|
113
123
|
|
|
@@ -123,17 +133,17 @@ Some other great aspects:
|
|
|
123
133
|
- Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
|
|
124
134
|
- Works with plain JavaScript too! You don't need to use TypeScript.
|
|
125
135
|
|
|
126
|
-
|
|
136
|
+
### Sponsors
|
|
127
137
|
|
|
128
138
|
Sponsorship at any level is appreciated and encouraged. For individual developers, consider the [Cup of Coffee tier](https://github.com/sponsors/colinhacks). If you built a paid product using Zod, consider one of the [podium tiers](https://github.com/sponsors/colinhacks).
|
|
129
139
|
|
|
130
|
-
|
|
140
|
+
#### Gold
|
|
131
141
|
|
|
132
142
|
<table>
|
|
133
143
|
<tr>
|
|
134
144
|
<td align="center">
|
|
135
145
|
<a href="https://astro.build/">
|
|
136
|
-
<img src="https://avatars.githubusercontent.com/u/44914786?s=200&v=4" width="200px;" alt="" />
|
|
146
|
+
<img src="https://avatars.githubusercontent.com/u/44914786?s=200&v=4" width="200px;" alt="Astro" />
|
|
137
147
|
</a>
|
|
138
148
|
<br />
|
|
139
149
|
<b>Astro</b>
|
|
@@ -173,7 +183,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
173
183
|
</tr>
|
|
174
184
|
</table>
|
|
175
185
|
|
|
176
|
-
|
|
186
|
+
#### Silver
|
|
177
187
|
|
|
178
188
|
<table>
|
|
179
189
|
<tr>
|
|
@@ -205,7 +215,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
205
215
|
</tr>
|
|
206
216
|
</table>
|
|
207
217
|
|
|
208
|
-
|
|
218
|
+
#### Bronze
|
|
209
219
|
|
|
210
220
|
<table>
|
|
211
221
|
<tr>
|
|
@@ -242,34 +252,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
242
252
|
</tr>
|
|
243
253
|
</table>
|
|
244
254
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
To install Zod v3:
|
|
248
|
-
|
|
249
|
-
```sh
|
|
250
|
-
npm install zod
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
⚠️ IMPORTANT: You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects.
|
|
254
|
-
|
|
255
|
-
```ts
|
|
256
|
-
// tsconfig.json
|
|
257
|
-
{
|
|
258
|
-
// ...
|
|
259
|
-
"compilerOptions": {
|
|
260
|
-
// ...
|
|
261
|
-
"strict": true
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
#### TypeScript requirements
|
|
267
|
-
|
|
268
|
-
- Zod 3.x requires TypeScript 4.1+
|
|
269
|
-
- Zod 2.x requires TypeScript 3.7+
|
|
270
|
-
- Zod 1.x requires TypeScript 3.3+
|
|
271
|
-
|
|
272
|
-
# Ecosystem
|
|
255
|
+
### Ecosystem
|
|
273
256
|
|
|
274
257
|
There are a growing number of tools that are built atop or support Zod natively! If you've built a tool or library on top of Zod, tell me about it [on Twitter](https://twitter.com/colinhacks) or [start a Discussion](https://github.com/colinhacks/zod/discussions). I'll add it below and tweet it out.
|
|
275
258
|
|
|
@@ -284,8 +267,8 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
284
267
|
- [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
|
|
285
268
|
- [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares.
|
|
286
269
|
- [`zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema): Convert your Zod schemas into [JSON Schemas](https://json-schema.org/).
|
|
287
|
-
- [`json-schema-to-zod`](https://github.com/StefanTerdell/json-schema-to-zod): Convert your [JSON Schemas](https://json-schema.org/) into Zod schemas.
|
|
288
|
-
- [`json-to-zod`](https://github.com/rsinohara/json-to-zod): Convert JSON objects into Zod schemas.
|
|
270
|
+
- [`json-schema-to-zod`](https://github.com/StefanTerdell/json-schema-to-zod): Convert your [JSON Schemas](https://json-schema.org/) into Zod schemas. [Live demo](https://StefanTerdell.github.io/json-schema-to-zod-react/).
|
|
271
|
+
- [`json-to-zod`](https://github.com/rsinohara/json-to-zod): Convert JSON objects into Zod schemas. [Live demo](https://rsinohara.github.io/json-to-zod-react/).
|
|
289
272
|
- [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema.
|
|
290
273
|
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
291
274
|
- [`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
|
|
@@ -293,14 +276,44 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
293
276
|
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas
|
|
294
277
|
- [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs
|
|
295
278
|
- [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters
|
|
279
|
+
- [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
|
|
280
|
+
- [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
|
|
281
|
+
- [`nestjs-graphql-zod`](https://github.com/incetarik/nestjs-graphql-zod): Generates NestJS GraphQL model classes from Zod schemas dynamically and provides GraphQL method decorators working with Zod schemas.
|
|
296
282
|
|
|
297
|
-
|
|
283
|
+
#### Form integrations
|
|
298
284
|
|
|
299
285
|
- [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form
|
|
300
286
|
- [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod
|
|
301
287
|
- [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod
|
|
302
288
|
|
|
303
|
-
|
|
289
|
+
## Installation
|
|
290
|
+
|
|
291
|
+
To install Zod v3:
|
|
292
|
+
|
|
293
|
+
```sh
|
|
294
|
+
npm install zod
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
⚠️ IMPORTANT: You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// tsconfig.json
|
|
301
|
+
{
|
|
302
|
+
// ...
|
|
303
|
+
"compilerOptions": {
|
|
304
|
+
// ...
|
|
305
|
+
"strict": true
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
> **TypeScript requirements**
|
|
311
|
+
>
|
|
312
|
+
> - Zod 3.x requires TypeScript 4.1+
|
|
313
|
+
> - Zod 2.x requires TypeScript 3.7+
|
|
314
|
+
> - Zod 1.x requires TypeScript 3.3+
|
|
315
|
+
|
|
316
|
+
## Basic usage
|
|
304
317
|
|
|
305
318
|
Creating a simple string schema
|
|
306
319
|
|
|
@@ -335,8 +348,6 @@ type User = z.infer<typeof User>;
|
|
|
335
348
|
// { username: string }
|
|
336
349
|
```
|
|
337
350
|
|
|
338
|
-
# Defining schemas
|
|
339
|
-
|
|
340
351
|
## Primitives
|
|
341
352
|
|
|
342
353
|
```ts
|
|
@@ -400,9 +411,7 @@ z.string().nonempty({ message: "Can't be empty" });
|
|
|
400
411
|
|
|
401
412
|
> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
|
|
402
413
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
You can customize certain errors when creating a string schema.
|
|
414
|
+
You can customize some common errors messages when creating a string schema.
|
|
406
415
|
|
|
407
416
|
```ts
|
|
408
417
|
const name = z.string({
|
|
@@ -548,7 +557,7 @@ FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
|
|
|
548
557
|
|
|
549
558
|
## Native enums
|
|
550
559
|
|
|
551
|
-
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()
|
|
560
|
+
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()`.
|
|
552
561
|
|
|
553
562
|
**Numeric enums**
|
|
554
563
|
|
|
@@ -616,7 +625,7 @@ FruitEnum.enum.Apple; // "apple"
|
|
|
616
625
|
|
|
617
626
|
## Optionals
|
|
618
627
|
|
|
619
|
-
You can make any schema optional with `z.optional()
|
|
628
|
+
You can make any schema optional with `z.optional()`. This wraps the schema in a `ZodOptional` instance and returns the result.
|
|
620
629
|
|
|
621
630
|
```ts
|
|
622
631
|
const schema = z.optional(z.string());
|
|
@@ -625,7 +634,7 @@ schema.parse(undefined); // => returns undefined
|
|
|
625
634
|
type A = z.infer<typeof schema>; // string | undefined
|
|
626
635
|
```
|
|
627
636
|
|
|
628
|
-
|
|
637
|
+
For convenience, you can also call the `.optional()` method on an existing schema.
|
|
629
638
|
|
|
630
639
|
```ts
|
|
631
640
|
const user = z.object({
|
|
@@ -634,7 +643,7 @@ const user = z.object({
|
|
|
634
643
|
type C = z.infer<typeof user>; // { username?: string | undefined };
|
|
635
644
|
```
|
|
636
645
|
|
|
637
|
-
|
|
646
|
+
You can extract the wrapped schema from a `ZodOptional` instance with `.unwrap()`.
|
|
638
647
|
|
|
639
648
|
```ts
|
|
640
649
|
const stringSchema = z.string();
|
|
@@ -644,7 +653,7 @@ optionalString.unwrap() === stringSchema; // true
|
|
|
644
653
|
|
|
645
654
|
## Nullables
|
|
646
655
|
|
|
647
|
-
Similarly, you can create nullable types
|
|
656
|
+
Similarly, you can create nullable types with `z.nullable()`.
|
|
648
657
|
|
|
649
658
|
```ts
|
|
650
659
|
const nullableString = z.nullable(z.string());
|
|
@@ -652,14 +661,14 @@ nullableString.parse("asdf"); // => "asdf"
|
|
|
652
661
|
nullableString.parse(null); // => null
|
|
653
662
|
```
|
|
654
663
|
|
|
655
|
-
|
|
664
|
+
Or use the `.nullable()` method.
|
|
656
665
|
|
|
657
666
|
```ts
|
|
658
667
|
const E = z.string().nullable(); // equivalent to D
|
|
659
668
|
type E = z.infer<typeof E>; // string | null
|
|
660
669
|
```
|
|
661
670
|
|
|
662
|
-
|
|
671
|
+
Extract the inner schema with `.unwrap()`.
|
|
663
672
|
|
|
664
673
|
```ts
|
|
665
674
|
const stringSchema = z.string();
|
|
@@ -815,7 +824,7 @@ const deepPartialUser = user.deepPartial();
|
|
|
815
824
|
|
|
816
825
|
> Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.
|
|
817
826
|
|
|
818
|
-
|
|
827
|
+
### `.passthrough`
|
|
819
828
|
|
|
820
829
|
By default Zod objects schemas strip out unrecognized keys during parsing.
|
|
821
830
|
|
|
@@ -832,8 +841,6 @@ person.parse({
|
|
|
832
841
|
// extraKey has been stripped
|
|
833
842
|
```
|
|
834
843
|
|
|
835
|
-
### `.passthrough`
|
|
836
|
-
|
|
837
844
|
Instead, if you want to pass through unknown keys, use `.passthrough()` .
|
|
838
845
|
|
|
839
846
|
```ts
|
|
@@ -846,7 +853,7 @@ person.passthrough().parse({
|
|
|
846
853
|
|
|
847
854
|
### `.strict`
|
|
848
855
|
|
|
849
|
-
You can _disallow_ unknown keys with `.strict()` . If there are any unknown keys in the input, Zod will throw an error.
|
|
856
|
+
By default Zod objects schemas strip out unrecognized keys during parsing. You can _disallow_ unknown keys with `.strict()` . If there are any unknown keys in the input, Zod will throw an error.
|
|
850
857
|
|
|
851
858
|
```ts
|
|
852
859
|
const person = z
|
|
@@ -983,7 +990,7 @@ For convenience, you can also use the `.or` method:
|
|
|
983
990
|
const stringOrNumber = z.string().or(z.number());
|
|
984
991
|
```
|
|
985
992
|
|
|
986
|
-
|
|
993
|
+
## Discriminated unions
|
|
987
994
|
|
|
988
995
|
If the union consists of object schemas all identifiable by a common property, it is possible to use
|
|
989
996
|
the `z.discriminatedUnion` method.
|
|
@@ -1029,7 +1036,7 @@ userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
|
|
|
1029
1036
|
}; // TypeError
|
|
1030
1037
|
```
|
|
1031
1038
|
|
|
1032
|
-
|
|
1039
|
+
**A note on numerical keys**
|
|
1033
1040
|
|
|
1034
1041
|
You may have expected `z.record()` to accept two arguments, one for the keys and one for the values. After all, TypeScript's built-in Record type does: `Record<KeyType, ValueType>` . Otherwise, how do you represent the TypeScript type `Record<number, any>` in Zod?
|
|
1035
1042
|
|
|
@@ -1046,9 +1053,7 @@ for (const key in testMap) {
|
|
|
1046
1053
|
// prints: `1: string`
|
|
1047
1054
|
```
|
|
1048
1055
|
|
|
1049
|
-
As you can see, JavaScript automatically casts all object keys to strings under the hood.
|
|
1050
|
-
|
|
1051
|
-
Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.
|
|
1056
|
+
As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.
|
|
1052
1057
|
|
|
1053
1058
|
## Maps
|
|
1054
1059
|
|
|
@@ -1067,7 +1072,7 @@ type NumberSet = z.infer<typeof numberSet>;
|
|
|
1067
1072
|
// type NumberSet = Set<number>
|
|
1068
1073
|
```
|
|
1069
1074
|
|
|
1070
|
-
|
|
1075
|
+
Set schemas can be further contrainted with the following utility methods.
|
|
1071
1076
|
|
|
1072
1077
|
```ts
|
|
1073
1078
|
z.set(z.string()).nonempty(); // must contain at least one item
|
|
@@ -1078,8 +1083,6 @@ z.set(z.string()).size(5); // must contain 5 items exactly
|
|
|
1078
1083
|
|
|
1079
1084
|
## Intersections
|
|
1080
1085
|
|
|
1081
|
-
<!-- > ⚠️ Intersections are deprecated. If you are trying to merge objects, use the `.merge` method instead. -->
|
|
1082
|
-
|
|
1083
1086
|
Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.
|
|
1084
1087
|
|
|
1085
1088
|
```ts
|
|
@@ -1181,7 +1184,7 @@ const Category: z.ZodType<Category> = BaseCategory.merge(
|
|
|
1181
1184
|
);
|
|
1182
1185
|
``` -->
|
|
1183
1186
|
|
|
1184
|
-
|
|
1187
|
+
### JSON type
|
|
1185
1188
|
|
|
1186
1189
|
If you want to validate any JSON value, you can use the snippet below.
|
|
1187
1190
|
|
|
@@ -1198,7 +1201,7 @@ jsonSchema.parse(data);
|
|
|
1198
1201
|
|
|
1199
1202
|
Thanks to [ggoodman](https://github.com/ggoodman) for suggesting this.
|
|
1200
1203
|
|
|
1201
|
-
|
|
1204
|
+
### Cyclical objects
|
|
1202
1205
|
|
|
1203
1206
|
Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop.
|
|
1204
1207
|
|
|
@@ -1262,7 +1265,7 @@ type myFunction = z.infer<typeof myFunction>;
|
|
|
1262
1265
|
// => ()=>unknown
|
|
1263
1266
|
```
|
|
1264
1267
|
|
|
1265
|
-
|
|
1268
|
+
Define inputs and outputs.
|
|
1266
1269
|
|
|
1267
1270
|
```ts
|
|
1268
1271
|
const myFunction = z
|
|
@@ -1273,24 +1276,6 @@ type myFunction = z.infer<typeof myFunction>;
|
|
|
1273
1276
|
// => (arg0: string, arg1: number)=>boolean
|
|
1274
1277
|
```
|
|
1275
1278
|
|
|
1276
|
-
**Extract the input and output schemas**
|
|
1277
|
-
You can extract the parameters and return type of a function schema.
|
|
1278
|
-
|
|
1279
|
-
```ts
|
|
1280
|
-
myFunction.parameters();
|
|
1281
|
-
// => ZodTuple<[ZodString, ZodNumber]>
|
|
1282
|
-
|
|
1283
|
-
myFunction.returnType();
|
|
1284
|
-
// => ZodBoolean
|
|
1285
|
-
```
|
|
1286
|
-
|
|
1287
|
-
<!-- `z.function()` accepts two arguments:
|
|
1288
|
-
|
|
1289
|
-
* `args: ZodTuple` The first argument is a tuple (created with `z.tuple([...])` and defines the schema of the arguments to your function. If the function doesn't accept arguments, you can pass an empty tuple (`z.tuple([])`).
|
|
1290
|
-
* `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
|
|
1291
|
-
|
|
1292
|
-
> You can use the special `z.void()` option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)
|
|
1293
|
-
|
|
1294
1279
|
<!--
|
|
1295
1280
|
|
|
1296
1281
|
``` ts
|
|
@@ -1319,7 +1304,9 @@ trimmedLength("sandwich"); // => 8
|
|
|
1319
1304
|
trimmedLength(" asdf "); // => 4
|
|
1320
1305
|
```
|
|
1321
1306
|
|
|
1322
|
-
If you only care about validating inputs,
|
|
1307
|
+
If you only care about validating inputs, just don't call the `.returns()` method. The output type will be inferred from the implementation.
|
|
1308
|
+
|
|
1309
|
+
> You can use the special `z.void()` option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)
|
|
1323
1310
|
|
|
1324
1311
|
```ts
|
|
1325
1312
|
const myFunction = z
|
|
@@ -1331,6 +1318,21 @@ const myFunction = z
|
|
|
1331
1318
|
myFunction; // (arg: string)=>number[]
|
|
1332
1319
|
```
|
|
1333
1320
|
|
|
1321
|
+
Extract the input and output schemas from a function schema.
|
|
1322
|
+
|
|
1323
|
+
```ts
|
|
1324
|
+
myFunction.parameters();
|
|
1325
|
+
// => ZodTuple<[ZodString, ZodNumber]>
|
|
1326
|
+
|
|
1327
|
+
myFunction.returnType();
|
|
1328
|
+
// => ZodBoolean
|
|
1329
|
+
```
|
|
1330
|
+
|
|
1331
|
+
<!-- `z.function()` accepts two arguments:
|
|
1332
|
+
|
|
1333
|
+
* `args: ZodTuple` The first argument is a tuple (created with `z.tuple([...])` and defines the schema of the arguments to your function. If the function doesn't accept arguments, you can pass an empty tuple (`z.tuple([])`).
|
|
1334
|
+
* `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
|
|
1335
|
+
|
|
1334
1336
|
## Preprocess
|
|
1335
1337
|
|
|
1336
1338
|
Typically Zod operates under a "parse then transform" paradigm. Zod validates the input first, then passes it through a chain of transformation functions. (For more information about transforms, read the [.transform docs](#transform).)
|
|
@@ -1343,7 +1345,7 @@ const castToString = z.preprocess((val) => String(val), z.string());
|
|
|
1343
1345
|
|
|
1344
1346
|
This returns a `ZodEffects` instance. `ZodEffects` is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.
|
|
1345
1347
|
|
|
1346
|
-
|
|
1348
|
+
## Schema methods
|
|
1347
1349
|
|
|
1348
1350
|
All Zod schemas contain certain methods.
|
|
1349
1351
|
|
|
@@ -1353,7 +1355,7 @@ All Zod schemas contain certain methods.
|
|
|
1353
1355
|
|
|
1354
1356
|
Given any Zod schema, you can call its `.parse` method to check `data` is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.
|
|
1355
1357
|
|
|
1356
|
-
> IMPORTANT:
|
|
1358
|
+
> IMPORTANT: The value returned by `.parse` is a _deep clone_ of the variable you passed in.
|
|
1357
1359
|
|
|
1358
1360
|
```ts
|
|
1359
1361
|
const stringSchema = z.string();
|
|
@@ -1368,8 +1370,11 @@ stringSchema.parse(12); // throws Error('Non-string type: number');
|
|
|
1368
1370
|
If you use asynchronous [refinements](#refine) or [transforms](#transform) (more on those later), you'll need to use `.parseAsync`
|
|
1369
1371
|
|
|
1370
1372
|
```ts
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1373
|
+
const stringSchema1 = z.string().refine(async (val) => val.length < 20);
|
|
1374
|
+
const value1 = await stringSchema.parseAsync("hello"); // => hello
|
|
1375
|
+
|
|
1376
|
+
const stringSchema2 = z.string().refine(async (val) => val.length > 20);
|
|
1377
|
+
const value2 = await stringSchema.parseAsync("hello"); // => throws
|
|
1373
1378
|
```
|
|
1374
1379
|
|
|
1375
1380
|
### `.safeParse`
|
|
@@ -1602,7 +1607,7 @@ const stringToNumber = z.string().transform((val) => myString.length);
|
|
|
1602
1607
|
stringToNumber.parse("string"); // => 6
|
|
1603
1608
|
```
|
|
1604
1609
|
|
|
1605
|
-
> ⚠️ Transform functions must not throw. Make sure to use refinements before the transform to make sure the input can be parsed by the transform.
|
|
1610
|
+
> ⚠️ Transform functions must not throw. Make sure to use refinements before the transform or addIssue within the transform to make sure the input can be parsed by the transform.
|
|
1606
1611
|
|
|
1607
1612
|
#### Chaining order
|
|
1608
1613
|
|
|
@@ -1617,14 +1622,33 @@ const emailToDomain = z
|
|
|
1617
1622
|
emailToDomain.parse("colinhacks@example.com"); // => example.com
|
|
1618
1623
|
```
|
|
1619
1624
|
|
|
1625
|
+
#### Validating during transform
|
|
1626
|
+
|
|
1627
|
+
Similar to `superRefine`, `transform` can optionally take a `ctx`. This allows you to simultaneously validate and transform the value, which can be simpler than chaining `refine` and `validate`. When calling `ctx.addIssue` make sure to still return a value of the correct type otherwise the inferred type will include `undefined`.
|
|
1628
|
+
|
|
1629
|
+
```ts
|
|
1630
|
+
const Strings = z.string().transform((val, ctx) => {
|
|
1631
|
+
const parsed = parseInt(val);
|
|
1632
|
+
if (isNaN(parsed)) {
|
|
1633
|
+
ctx.addIssue({
|
|
1634
|
+
code: z.ZodIssueCode.custom,
|
|
1635
|
+
message: "Not a number",
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
return parsed;
|
|
1639
|
+
});
|
|
1640
|
+
```
|
|
1641
|
+
|
|
1620
1642
|
#### Relationship to refinements
|
|
1621
1643
|
|
|
1622
|
-
Transforms and refinements can be interleaved
|
|
1644
|
+
Transforms and refinements can be interleaved. These will be executed in the order they are declared.
|
|
1623
1645
|
|
|
1624
1646
|
```ts
|
|
1625
1647
|
z.string()
|
|
1626
|
-
.transform((val) => val.
|
|
1627
|
-
.refine((val) => val >
|
|
1648
|
+
.transform((val) => val.toUpperCase())
|
|
1649
|
+
.refine((val) => val.length > 15)
|
|
1650
|
+
.transform((val) => `Hello ${val}`)
|
|
1651
|
+
.refine((val) => val.indexOf("!") === -1);
|
|
1628
1652
|
```
|
|
1629
1653
|
|
|
1630
1654
|
#### Async transforms
|
|
@@ -1686,7 +1710,7 @@ z.nullable(z.string());
|
|
|
1686
1710
|
|
|
1687
1711
|
### `.nullish`
|
|
1688
1712
|
|
|
1689
|
-
A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both `undefined` and `null`. Read more about the concept of "nullish" [
|
|
1713
|
+
A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both `undefined` and `null`. Read more about the concept of "nullish" [in the TypeScript 3.7 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing).
|
|
1690
1714
|
|
|
1691
1715
|
```ts
|
|
1692
1716
|
const nullishString = z.string().nullish(); // string | null | undefined
|
|
@@ -1739,9 +1763,9 @@ z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: st
|
|
|
1739
1763
|
z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
|
1740
1764
|
```
|
|
1741
1765
|
|
|
1742
|
-
|
|
1766
|
+
## Guides and concepts
|
|
1743
1767
|
|
|
1744
|
-
|
|
1768
|
+
### Type inference
|
|
1745
1769
|
|
|
1746
1770
|
You can extract the TypeScript type of any schema with `z.infer<typeof mySchema>` .
|
|
1747
1771
|
|
|
@@ -1753,7 +1777,7 @@ const u: A = 12; // TypeError
|
|
|
1753
1777
|
const u: A = "asdf"; // compiles
|
|
1754
1778
|
```
|
|
1755
1779
|
|
|
1756
|
-
|
|
1780
|
+
**What about transforms?**
|
|
1757
1781
|
|
|
1758
1782
|
In reality each Zod schema internally tracks **two** types: an input and an output. For most schemas (e.g. `z.string()`) these two are the same. But once you add transforms into the mix, these two values can diverge. For instance `z.string().transform(val => val.length)` has an input of `string` and an output of `number`.
|
|
1759
1783
|
|
|
@@ -1770,7 +1794,7 @@ type output = z.output<typeof stringToNumber>; // number
|
|
|
1770
1794
|
type inferred = z.infer<typeof stringToNumber>; // number
|
|
1771
1795
|
```
|
|
1772
1796
|
|
|
1773
|
-
|
|
1797
|
+
### Writing generic functions
|
|
1774
1798
|
|
|
1775
1799
|
When attempting to write a functions that accepts a Zod schemas as an input, it's common to try something like this:
|
|
1776
1800
|
|
|
@@ -1804,13 +1828,13 @@ const arg = makeSchemaOptional(z.string());
|
|
|
1804
1828
|
arg.unwrap(); // ZodString
|
|
1805
1829
|
```
|
|
1806
1830
|
|
|
1807
|
-
|
|
1831
|
+
#### Constraining allowable inputs
|
|
1808
1832
|
|
|
1809
1833
|
The `ZodType` class has three generic parameters.
|
|
1810
1834
|
|
|
1811
1835
|
```ts
|
|
1812
1836
|
class ZodType<
|
|
1813
|
-
Output,
|
|
1837
|
+
Output = any,
|
|
1814
1838
|
Def extends ZodTypeDef = ZodTypeDef,
|
|
1815
1839
|
Input = Output
|
|
1816
1840
|
> { ... }
|
|
@@ -1830,12 +1854,16 @@ makeSchemaOptional(z.number());
|
|
|
1830
1854
|
// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType<string, ZodTypeDef, string>'
|
|
1831
1855
|
```
|
|
1832
1856
|
|
|
1833
|
-
|
|
1857
|
+
### Error handling
|
|
1834
1858
|
|
|
1835
1859
|
Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.
|
|
1836
1860
|
|
|
1837
1861
|
```ts
|
|
1838
|
-
const data = z
|
|
1862
|
+
const data = z
|
|
1863
|
+
.object({
|
|
1864
|
+
name: z.string(),
|
|
1865
|
+
})
|
|
1866
|
+
.safeParse({ name: 12 });
|
|
1839
1867
|
|
|
1840
1868
|
if (!data.success) {
|
|
1841
1869
|
data.error.issues;
|
|
@@ -1851,20 +1879,31 @@ if (!data.success) {
|
|
|
1851
1879
|
}
|
|
1852
1880
|
```
|
|
1853
1881
|
|
|
1854
|
-
|
|
1882
|
+
> For detailed information about the possible error codes and how to customize error messages, check out the dedicated error handling guide: [ERROR_HANDLING.md](ERROR_HANDLING.md)
|
|
1883
|
+
|
|
1884
|
+
### Error formatting
|
|
1855
1885
|
|
|
1856
1886
|
You can use the `.format()` method to convert this error into a nested object.
|
|
1857
1887
|
|
|
1858
1888
|
```ts
|
|
1859
|
-
data
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1889
|
+
const data = z
|
|
1890
|
+
.object({
|
|
1891
|
+
name: z.string(),
|
|
1892
|
+
})
|
|
1893
|
+
.safeParse({ name: 12 });
|
|
1864
1894
|
|
|
1865
|
-
|
|
1895
|
+
if (!data.success) {
|
|
1896
|
+
const formatted = data.error.format();
|
|
1897
|
+
/* {
|
|
1898
|
+
name: { _errors: [ 'Expected string, received number' ] }
|
|
1899
|
+
} */
|
|
1866
1900
|
|
|
1867
|
-
|
|
1901
|
+
formatted.name?._errors;
|
|
1902
|
+
// => ["Expected string, received number"]
|
|
1903
|
+
}
|
|
1904
|
+
```
|
|
1905
|
+
|
|
1906
|
+
## Comparison
|
|
1868
1907
|
|
|
1869
1908
|
There are a handful of other widely-used validation libraries, but all of them have certain design limitations that make for a non-ideal developer experience.
|
|
1870
1909
|
|
|
@@ -1916,20 +1955,18 @@ Branded -->
|
|
|
1916
1955
|
* Missing support for parsing cyclical data (maybe)
|
|
1917
1956
|
* Missing error customization -->
|
|
1918
1957
|
|
|
1919
|
-
|
|
1958
|
+
**Joi**
|
|
1920
1959
|
|
|
1921
1960
|
[https://github.com/hapijs/joi](https://github.com/hapijs/joi)
|
|
1922
1961
|
|
|
1923
1962
|
Doesn't support static type inference 😕
|
|
1924
1963
|
|
|
1925
|
-
|
|
1964
|
+
**Yup**
|
|
1926
1965
|
|
|
1927
1966
|
[https://github.com/jquense/yup](https://github.com/jquense/yup)
|
|
1928
1967
|
|
|
1929
1968
|
Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.
|
|
1930
1969
|
|
|
1931
|
-
Differences
|
|
1932
|
-
|
|
1933
1970
|
- Supports casting and transforms
|
|
1934
1971
|
- All object fields are optional by default
|
|
1935
1972
|
- Missing object methods: (partial, deepPartial)
|
|
@@ -1940,7 +1977,7 @@ Differences
|
|
|
1940
1977
|
|
|
1941
1978
|
<!-- ¹Yup has a strange interpretation of the word `required`. Instead of meaning "not undefined", Yup uses it to mean "not empty". So `yup.string().required()` will not accept an empty string, and `yup.array(yup.string()).required()` will not accept an empty array. Instead, Yup us Zod arrays there is a dedicated `.nonempty()` method to indicate this, or you can implement it with a custom refinement. -->
|
|
1942
1979
|
|
|
1943
|
-
|
|
1980
|
+
**io-ts**
|
|
1944
1981
|
|
|
1945
1982
|
[https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)
|
|
1946
1983
|
|
|
@@ -1991,7 +2028,7 @@ This more declarative API makes schema definitions vastly more concise.
|
|
|
1991
2028
|
- Missing promise schemas
|
|
1992
2029
|
- Missing function schemas
|
|
1993
2030
|
|
|
1994
|
-
|
|
2031
|
+
**Runtypes**
|
|
1995
2032
|
|
|
1996
2033
|
[https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
|
|
1997
2034
|
|
|
@@ -2004,7 +2041,7 @@ Good type inference support, but limited options for object type masking (no `.p
|
|
|
2004
2041
|
- Missing promise schemas
|
|
2005
2042
|
- Missing error customization
|
|
2006
2043
|
|
|
2007
|
-
|
|
2044
|
+
**Ow**
|
|
2008
2045
|
|
|
2009
2046
|
[https://github.com/sindresorhus/ow](https://github.com/sindresorhus/ow)
|
|
2010
2047
|
|
|
@@ -2012,6 +2049,6 @@ Ow is focused on function input validation. It's a library that makes it easy to
|
|
|
2012
2049
|
|
|
2013
2050
|
If you want to validate function inputs, use function schemas in Zod! It's a much simpler approach that lets you reuse a function type declaration without repeating yourself (namely, copy-pasting a bunch of ow assertions at the beginning of every function). Also Zod lets you validate your return types as well, so you can be sure there won't be any unexpected data passed downstream.
|
|
2014
2051
|
|
|
2015
|
-
|
|
2052
|
+
## Changelog
|
|
2016
2053
|
|
|
2017
2054
|
View the changelog at [CHANGELOG.md](CHANGELOG.md)
|