zod 3.16.0 → 3.17.2
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 +218 -183
- package/lib/ZodError.d.ts +1 -2
- package/lib/ZodError.js +1 -2
- package/lib/external.d.ts +1 -0
- package/lib/external.js +4 -0
- package/lib/helpers/parseUtil.d.ts +2 -25
- package/lib/helpers/parseUtil.js +1 -67
- package/lib/helpers/util.d.ts +24 -0
- package/lib/helpers/util.js +66 -1
- package/lib/index.mjs +91 -72
- package/lib/index.umd.js +91 -72
- package/lib/types.d.ts +9 -5
- package/lib/types.js +80 -61
- package/package.json +2 -2
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,64 @@
|
|
|
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
|
-
- [
|
|
50
|
+
- [Node](#node)
|
|
51
|
+
- [Deno](#deno)
|
|
40
52
|
- [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)
|
|
53
|
+
- [Primitives](#primitives)
|
|
54
|
+
- [Literals](#literals)
|
|
55
|
+
- [Strings](#strings)
|
|
56
|
+
- [Numbers](#numbers)
|
|
57
|
+
- [NaNs](#nans)
|
|
58
|
+
- [Booleans](#booleans)
|
|
59
|
+
- [Dates](#dates)
|
|
60
|
+
- [Zod enums](#zod-enums)
|
|
61
|
+
- [Native enums](#native-enums)
|
|
62
|
+
- [Optionals](#optionals)
|
|
63
|
+
- [Nullables](#nullables)
|
|
64
|
+
- [Objects](#objects)
|
|
65
|
+
- [.shape](#shape)
|
|
66
|
+
- [.extend](#extend)
|
|
67
|
+
- [.merge](#merge)
|
|
68
|
+
- [.pick/.omit](#pickomit)
|
|
69
|
+
- [.partial](#partial)
|
|
70
|
+
- [.deepPartial](#deepPartial)
|
|
71
|
+
- [.passthrough](#passthrough)
|
|
72
|
+
- [.strict](#strict)
|
|
73
|
+
- [.strip](#strip)
|
|
74
|
+
- [.catchall](#catchall)
|
|
75
|
+
- [Arrays](#arrays)
|
|
76
|
+
- [.element](#element)
|
|
77
|
+
- [.nonempty](#nonempty)
|
|
78
|
+
- [.min/.max/.length](#minmaxlength)
|
|
79
|
+
- [Tuples](#tuples)
|
|
80
|
+
- [Unions](#unions)
|
|
81
|
+
- [Discriminated Unions](#discriminated-unions)
|
|
82
|
+
- [Records](#records)
|
|
83
|
+
- [Maps](#maps)
|
|
84
|
+
- [Sets](#sets)
|
|
85
|
+
- [Recursive types](#recursive-types)
|
|
86
|
+
- [JSON type](#json-type)
|
|
87
|
+
- [Cyclical data](#cyclical-objects)
|
|
88
|
+
- [Promises](#promises)
|
|
89
|
+
- [Instanceof](#instanceof)
|
|
90
|
+
- [Function schemas](#function-schemas)
|
|
91
|
+
- [Preprocess](#preprocess)
|
|
92
|
+
- [Schema methods](#schema-methods)
|
|
82
93
|
- [.parse](#parse)
|
|
83
94
|
- [.parseAsync](#parseasync)
|
|
84
95
|
- [.safeParse](#safeparse)
|
|
@@ -98,6 +109,7 @@ These docs have been translated into [Chinese](./README_ZH.md).
|
|
|
98
109
|
- [Type inference](#type-inference)
|
|
99
110
|
- [Writing generic functions](#writing-generic-functions)
|
|
100
111
|
- [Error handling](#error-handling)
|
|
112
|
+
- [Error formatting](#error-formatting)
|
|
101
113
|
- [Comparison](#comparison)
|
|
102
114
|
- [Joi](#joi)
|
|
103
115
|
- [Yup](#yup)
|
|
@@ -107,7 +119,7 @@ These docs have been translated into [Chinese](./README_ZH.md).
|
|
|
107
119
|
|
|
108
120
|
<!-- **Zod 2 is coming! Follow [@colinhacks](https://twitter.com/colinhacks) to stay updated and discuss the future of Zod.** -->
|
|
109
121
|
|
|
110
|
-
|
|
122
|
+
## Introduction
|
|
111
123
|
|
|
112
124
|
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
125
|
|
|
@@ -123,17 +135,17 @@ Some other great aspects:
|
|
|
123
135
|
- Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
|
|
124
136
|
- Works with plain JavaScript too! You don't need to use TypeScript.
|
|
125
137
|
|
|
126
|
-
|
|
138
|
+
### Sponsors
|
|
127
139
|
|
|
128
140
|
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
141
|
|
|
130
|
-
|
|
142
|
+
#### Gold
|
|
131
143
|
|
|
132
144
|
<table>
|
|
133
145
|
<tr>
|
|
134
146
|
<td align="center">
|
|
135
147
|
<a href="https://astro.build/">
|
|
136
|
-
<img src="https://avatars.githubusercontent.com/u/44914786?s=200&v=4" width="200px;" alt="" />
|
|
148
|
+
<img src="https://avatars.githubusercontent.com/u/44914786?s=200&v=4" width="200px;" alt="Astro" />
|
|
137
149
|
</a>
|
|
138
150
|
<br />
|
|
139
151
|
<b>Astro</b>
|
|
@@ -173,7 +185,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
173
185
|
</tr>
|
|
174
186
|
</table>
|
|
175
187
|
|
|
176
|
-
|
|
188
|
+
#### Silver
|
|
177
189
|
|
|
178
190
|
<table>
|
|
179
191
|
<tr>
|
|
@@ -205,7 +217,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
205
217
|
</tr>
|
|
206
218
|
</table>
|
|
207
219
|
|
|
208
|
-
|
|
220
|
+
#### Bronze
|
|
209
221
|
|
|
210
222
|
<table>
|
|
211
223
|
<tr>
|
|
@@ -242,34 +254,7 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
242
254
|
</tr>
|
|
243
255
|
</table>
|
|
244
256
|
|
|
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
|
|
257
|
+
### Ecosystem
|
|
273
258
|
|
|
274
259
|
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
260
|
|
|
@@ -284,8 +269,8 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
284
269
|
- [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
|
|
285
270
|
- [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares.
|
|
286
271
|
- [`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.
|
|
272
|
+
- [`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/).
|
|
273
|
+
- [`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
274
|
- [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema.
|
|
290
275
|
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
291
276
|
- [`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
|
|
@@ -297,13 +282,57 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
297
282
|
- [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
|
|
298
283
|
- [`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.
|
|
299
284
|
|
|
300
|
-
|
|
285
|
+
#### Form integrations
|
|
301
286
|
|
|
302
287
|
- [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form
|
|
303
288
|
- [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod
|
|
304
289
|
- [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod
|
|
305
290
|
|
|
306
|
-
|
|
291
|
+
## Installation
|
|
292
|
+
|
|
293
|
+
### Requirements
|
|
294
|
+
|
|
295
|
+
- TypeScript 4.1+!
|
|
296
|
+
- You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects.
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
// tsconfig.json
|
|
300
|
+
{
|
|
301
|
+
// ...
|
|
302
|
+
"compilerOptions": {
|
|
303
|
+
// ...
|
|
304
|
+
"strict": true
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Node/NPM
|
|
310
|
+
|
|
311
|
+
To install Zod v3:
|
|
312
|
+
|
|
313
|
+
```sh
|
|
314
|
+
npm install zod # npm
|
|
315
|
+
yarn add zod # yarn
|
|
316
|
+
pnpm add zod # pnpm
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Deno
|
|
320
|
+
|
|
321
|
+
Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on [deno.land/x](deno.land/x). The latest version can be imported like so:
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
import { z } from "https://deno.land/x/zod/mod.ts";
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
You can also specify a particular version:
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
import { z } from from "https://deno.land/x/zod@v3.16.1/mod.ts"
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
> The rest of this README assumes you are using NPM and importing directly from the `"zod"` package.
|
|
334
|
+
|
|
335
|
+
## Basic usage
|
|
307
336
|
|
|
308
337
|
Creating a simple string schema
|
|
309
338
|
|
|
@@ -338,8 +367,6 @@ type User = z.infer<typeof User>;
|
|
|
338
367
|
// { username: string }
|
|
339
368
|
```
|
|
340
369
|
|
|
341
|
-
# Defining schemas
|
|
342
|
-
|
|
343
370
|
## Primitives
|
|
344
371
|
|
|
345
372
|
```ts
|
|
@@ -394,6 +421,9 @@ z.string().uuid();
|
|
|
394
421
|
z.string().cuid();
|
|
395
422
|
z.string().regex(regex);
|
|
396
423
|
|
|
424
|
+
// trim whitespace
|
|
425
|
+
z.string().trim();
|
|
426
|
+
|
|
397
427
|
// deprecated, equivalent to .min(1)
|
|
398
428
|
z.string().nonempty();
|
|
399
429
|
|
|
@@ -403,9 +433,7 @@ z.string().nonempty({ message: "Can't be empty" });
|
|
|
403
433
|
|
|
404
434
|
> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
|
|
405
435
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
You can customize certain errors when creating a string schema.
|
|
436
|
+
You can customize some common errors messages when creating a string schema.
|
|
409
437
|
|
|
410
438
|
```ts
|
|
411
439
|
const name = z.string({
|
|
@@ -551,7 +579,7 @@ FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
|
|
|
551
579
|
|
|
552
580
|
## Native enums
|
|
553
581
|
|
|
554
|
-
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()
|
|
582
|
+
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()`.
|
|
555
583
|
|
|
556
584
|
**Numeric enums**
|
|
557
585
|
|
|
@@ -619,7 +647,7 @@ FruitEnum.enum.Apple; // "apple"
|
|
|
619
647
|
|
|
620
648
|
## Optionals
|
|
621
649
|
|
|
622
|
-
You can make any schema optional with `z.optional()
|
|
650
|
+
You can make any schema optional with `z.optional()`. This wraps the schema in a `ZodOptional` instance and returns the result.
|
|
623
651
|
|
|
624
652
|
```ts
|
|
625
653
|
const schema = z.optional(z.string());
|
|
@@ -628,7 +656,7 @@ schema.parse(undefined); // => returns undefined
|
|
|
628
656
|
type A = z.infer<typeof schema>; // string | undefined
|
|
629
657
|
```
|
|
630
658
|
|
|
631
|
-
|
|
659
|
+
For convenience, you can also call the `.optional()` method on an existing schema.
|
|
632
660
|
|
|
633
661
|
```ts
|
|
634
662
|
const user = z.object({
|
|
@@ -637,7 +665,7 @@ const user = z.object({
|
|
|
637
665
|
type C = z.infer<typeof user>; // { username?: string | undefined };
|
|
638
666
|
```
|
|
639
667
|
|
|
640
|
-
|
|
668
|
+
You can extract the wrapped schema from a `ZodOptional` instance with `.unwrap()`.
|
|
641
669
|
|
|
642
670
|
```ts
|
|
643
671
|
const stringSchema = z.string();
|
|
@@ -647,7 +675,7 @@ optionalString.unwrap() === stringSchema; // true
|
|
|
647
675
|
|
|
648
676
|
## Nullables
|
|
649
677
|
|
|
650
|
-
Similarly, you can create nullable types
|
|
678
|
+
Similarly, you can create nullable types with `z.nullable()`.
|
|
651
679
|
|
|
652
680
|
```ts
|
|
653
681
|
const nullableString = z.nullable(z.string());
|
|
@@ -655,14 +683,14 @@ nullableString.parse("asdf"); // => "asdf"
|
|
|
655
683
|
nullableString.parse(null); // => null
|
|
656
684
|
```
|
|
657
685
|
|
|
658
|
-
|
|
686
|
+
Or use the `.nullable()` method.
|
|
659
687
|
|
|
660
688
|
```ts
|
|
661
689
|
const E = z.string().nullable(); // equivalent to D
|
|
662
690
|
type E = z.infer<typeof E>; // string | null
|
|
663
691
|
```
|
|
664
692
|
|
|
665
|
-
|
|
693
|
+
Extract the inner schema with `.unwrap()`.
|
|
666
694
|
|
|
667
695
|
```ts
|
|
668
696
|
const stringSchema = z.string();
|
|
@@ -818,7 +846,7 @@ const deepPartialUser = user.deepPartial();
|
|
|
818
846
|
|
|
819
847
|
> Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.
|
|
820
848
|
|
|
821
|
-
|
|
849
|
+
### `.passthrough`
|
|
822
850
|
|
|
823
851
|
By default Zod objects schemas strip out unrecognized keys during parsing.
|
|
824
852
|
|
|
@@ -835,8 +863,6 @@ person.parse({
|
|
|
835
863
|
// extraKey has been stripped
|
|
836
864
|
```
|
|
837
865
|
|
|
838
|
-
### `.passthrough`
|
|
839
|
-
|
|
840
866
|
Instead, if you want to pass through unknown keys, use `.passthrough()` .
|
|
841
867
|
|
|
842
868
|
```ts
|
|
@@ -849,7 +875,7 @@ person.passthrough().parse({
|
|
|
849
875
|
|
|
850
876
|
### `.strict`
|
|
851
877
|
|
|
852
|
-
You can _disallow_ unknown keys with `.strict()` . If there are any unknown keys in the input, Zod will throw an error.
|
|
878
|
+
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.
|
|
853
879
|
|
|
854
880
|
```ts
|
|
855
881
|
const person = z
|
|
@@ -986,7 +1012,7 @@ For convenience, you can also use the `.or` method:
|
|
|
986
1012
|
const stringOrNumber = z.string().or(z.number());
|
|
987
1013
|
```
|
|
988
1014
|
|
|
989
|
-
|
|
1015
|
+
## Discriminated unions
|
|
990
1016
|
|
|
991
1017
|
If the union consists of object schemas all identifiable by a common property, it is possible to use
|
|
992
1018
|
the `z.discriminatedUnion` method.
|
|
@@ -1032,7 +1058,7 @@ userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
|
|
|
1032
1058
|
}; // TypeError
|
|
1033
1059
|
```
|
|
1034
1060
|
|
|
1035
|
-
|
|
1061
|
+
**A note on numerical keys**
|
|
1036
1062
|
|
|
1037
1063
|
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?
|
|
1038
1064
|
|
|
@@ -1049,9 +1075,7 @@ for (const key in testMap) {
|
|
|
1049
1075
|
// prints: `1: string`
|
|
1050
1076
|
```
|
|
1051
1077
|
|
|
1052
|
-
As you can see, JavaScript automatically casts all object keys to strings under the hood.
|
|
1053
|
-
|
|
1054
|
-
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.
|
|
1078
|
+
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.
|
|
1055
1079
|
|
|
1056
1080
|
## Maps
|
|
1057
1081
|
|
|
@@ -1070,7 +1094,7 @@ type NumberSet = z.infer<typeof numberSet>;
|
|
|
1070
1094
|
// type NumberSet = Set<number>
|
|
1071
1095
|
```
|
|
1072
1096
|
|
|
1073
|
-
|
|
1097
|
+
Set schemas can be further contrainted with the following utility methods.
|
|
1074
1098
|
|
|
1075
1099
|
```ts
|
|
1076
1100
|
z.set(z.string()).nonempty(); // must contain at least one item
|
|
@@ -1081,8 +1105,6 @@ z.set(z.string()).size(5); // must contain 5 items exactly
|
|
|
1081
1105
|
|
|
1082
1106
|
## Intersections
|
|
1083
1107
|
|
|
1084
|
-
<!-- > ⚠️ Intersections are deprecated. If you are trying to merge objects, use the `.merge` method instead. -->
|
|
1085
|
-
|
|
1086
1108
|
Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.
|
|
1087
1109
|
|
|
1088
1110
|
```ts
|
|
@@ -1184,7 +1206,7 @@ const Category: z.ZodType<Category> = BaseCategory.merge(
|
|
|
1184
1206
|
);
|
|
1185
1207
|
``` -->
|
|
1186
1208
|
|
|
1187
|
-
|
|
1209
|
+
### JSON type
|
|
1188
1210
|
|
|
1189
1211
|
If you want to validate any JSON value, you can use the snippet below.
|
|
1190
1212
|
|
|
@@ -1201,7 +1223,7 @@ jsonSchema.parse(data);
|
|
|
1201
1223
|
|
|
1202
1224
|
Thanks to [ggoodman](https://github.com/ggoodman) for suggesting this.
|
|
1203
1225
|
|
|
1204
|
-
|
|
1226
|
+
### Cyclical objects
|
|
1205
1227
|
|
|
1206
1228
|
Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop.
|
|
1207
1229
|
|
|
@@ -1265,7 +1287,7 @@ type myFunction = z.infer<typeof myFunction>;
|
|
|
1265
1287
|
// => ()=>unknown
|
|
1266
1288
|
```
|
|
1267
1289
|
|
|
1268
|
-
|
|
1290
|
+
Define inputs and outputs.
|
|
1269
1291
|
|
|
1270
1292
|
```ts
|
|
1271
1293
|
const myFunction = z
|
|
@@ -1276,24 +1298,6 @@ type myFunction = z.infer<typeof myFunction>;
|
|
|
1276
1298
|
// => (arg0: string, arg1: number)=>boolean
|
|
1277
1299
|
```
|
|
1278
1300
|
|
|
1279
|
-
**Extract the input and output schemas**
|
|
1280
|
-
You can extract the parameters and return type of a function schema.
|
|
1281
|
-
|
|
1282
|
-
```ts
|
|
1283
|
-
myFunction.parameters();
|
|
1284
|
-
// => ZodTuple<[ZodString, ZodNumber]>
|
|
1285
|
-
|
|
1286
|
-
myFunction.returnType();
|
|
1287
|
-
// => ZodBoolean
|
|
1288
|
-
```
|
|
1289
|
-
|
|
1290
|
-
<!-- `z.function()` accepts two arguments:
|
|
1291
|
-
|
|
1292
|
-
* `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([])`).
|
|
1293
|
-
* `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
|
|
1294
|
-
|
|
1295
|
-
> 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.)
|
|
1296
|
-
|
|
1297
1301
|
<!--
|
|
1298
1302
|
|
|
1299
1303
|
``` ts
|
|
@@ -1322,7 +1326,9 @@ trimmedLength("sandwich"); // => 8
|
|
|
1322
1326
|
trimmedLength(" asdf "); // => 4
|
|
1323
1327
|
```
|
|
1324
1328
|
|
|
1325
|
-
If you only care about validating inputs,
|
|
1329
|
+
If you only care about validating inputs, just don't call the `.returns()` method. The output type will be inferred from the implementation.
|
|
1330
|
+
|
|
1331
|
+
> 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.)
|
|
1326
1332
|
|
|
1327
1333
|
```ts
|
|
1328
1334
|
const myFunction = z
|
|
@@ -1334,6 +1340,21 @@ const myFunction = z
|
|
|
1334
1340
|
myFunction; // (arg: string)=>number[]
|
|
1335
1341
|
```
|
|
1336
1342
|
|
|
1343
|
+
Extract the input and output schemas from a function schema.
|
|
1344
|
+
|
|
1345
|
+
```ts
|
|
1346
|
+
myFunction.parameters();
|
|
1347
|
+
// => ZodTuple<[ZodString, ZodNumber]>
|
|
1348
|
+
|
|
1349
|
+
myFunction.returnType();
|
|
1350
|
+
// => ZodBoolean
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
<!-- `z.function()` accepts two arguments:
|
|
1354
|
+
|
|
1355
|
+
* `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([])`).
|
|
1356
|
+
* `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
|
|
1357
|
+
|
|
1337
1358
|
## Preprocess
|
|
1338
1359
|
|
|
1339
1360
|
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).)
|
|
@@ -1346,7 +1367,7 @@ const castToString = z.preprocess((val) => String(val), z.string());
|
|
|
1346
1367
|
|
|
1347
1368
|
This returns a `ZodEffects` instance. `ZodEffects` is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.
|
|
1348
1369
|
|
|
1349
|
-
|
|
1370
|
+
## Schema methods
|
|
1350
1371
|
|
|
1351
1372
|
All Zod schemas contain certain methods.
|
|
1352
1373
|
|
|
@@ -1371,8 +1392,11 @@ stringSchema.parse(12); // throws Error('Non-string type: number');
|
|
|
1371
1392
|
If you use asynchronous [refinements](#refine) or [transforms](#transform) (more on those later), you'll need to use `.parseAsync`
|
|
1372
1393
|
|
|
1373
1394
|
```ts
|
|
1374
|
-
const
|
|
1375
|
-
const
|
|
1395
|
+
const stringSchema1 = z.string().refine(async (val) => val.length < 20);
|
|
1396
|
+
const value1 = await stringSchema.parseAsync("hello"); // => hello
|
|
1397
|
+
|
|
1398
|
+
const stringSchema2 = z.string().refine(async (val) => val.length > 20);
|
|
1399
|
+
const value2 = await stringSchema.parseAsync("hello"); // => throws
|
|
1376
1400
|
```
|
|
1377
1401
|
|
|
1378
1402
|
### `.safeParse`
|
|
@@ -1607,27 +1631,6 @@ stringToNumber.parse("string"); // => 6
|
|
|
1607
1631
|
|
|
1608
1632
|
> ⚠️ 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.
|
|
1609
1633
|
|
|
1610
|
-
#### Validating during transform
|
|
1611
|
-
|
|
1612
|
-
Similar to `superRefine`, `transform` can optionally take a `ctx`. This allows you to simultaneously
|
|
1613
|
-
validate and transform the value, which can be simpler than chaining `refine` and `validate`.
|
|
1614
|
-
When calling `ctx.addIssue` make sure to still return a value of the correct type otherwise the inferred type will include `undefined`.
|
|
1615
|
-
|
|
1616
|
-
```ts
|
|
1617
|
-
const Strings = z
|
|
1618
|
-
.string()
|
|
1619
|
-
.transform((val, ctx) => {
|
|
1620
|
-
const parsed = parseInt(val);
|
|
1621
|
-
if (isNaN(parsed)) {
|
|
1622
|
-
ctx.addIssue({
|
|
1623
|
-
code: z.ZodIssueCode.custom,
|
|
1624
|
-
message: "Not a number",
|
|
1625
|
-
});
|
|
1626
|
-
}
|
|
1627
|
-
return parsed;
|
|
1628
|
-
});
|
|
1629
|
-
```
|
|
1630
|
-
|
|
1631
1634
|
#### Chaining order
|
|
1632
1635
|
|
|
1633
1636
|
Note that `stringToNumber` above is an instance of the `ZodEffects` subclass. It is NOT an instance of `ZodString`. If you want to use the built-in methods of `ZodString` (e.g. `.email()`) you must apply those methods _before_ any transforms.
|
|
@@ -1641,14 +1644,33 @@ const emailToDomain = z
|
|
|
1641
1644
|
emailToDomain.parse("colinhacks@example.com"); // => example.com
|
|
1642
1645
|
```
|
|
1643
1646
|
|
|
1647
|
+
#### Validating during transform
|
|
1648
|
+
|
|
1649
|
+
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`.
|
|
1650
|
+
|
|
1651
|
+
```ts
|
|
1652
|
+
const Strings = z.string().transform((val, ctx) => {
|
|
1653
|
+
const parsed = parseInt(val);
|
|
1654
|
+
if (isNaN(parsed)) {
|
|
1655
|
+
ctx.addIssue({
|
|
1656
|
+
code: z.ZodIssueCode.custom,
|
|
1657
|
+
message: "Not a number",
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
return parsed;
|
|
1661
|
+
});
|
|
1662
|
+
```
|
|
1663
|
+
|
|
1644
1664
|
#### Relationship to refinements
|
|
1645
1665
|
|
|
1646
|
-
Transforms and refinements can be interleaved
|
|
1666
|
+
Transforms and refinements can be interleaved. These will be executed in the order they are declared.
|
|
1647
1667
|
|
|
1648
1668
|
```ts
|
|
1649
1669
|
z.string()
|
|
1650
|
-
.transform((val) => val.
|
|
1651
|
-
.refine((val) => val >
|
|
1670
|
+
.transform((val) => val.toUpperCase())
|
|
1671
|
+
.refine((val) => val.length > 15)
|
|
1672
|
+
.transform((val) => `Hello ${val}`)
|
|
1673
|
+
.refine((val) => val.indexOf("!") === -1);
|
|
1652
1674
|
```
|
|
1653
1675
|
|
|
1654
1676
|
#### Async transforms
|
|
@@ -1710,7 +1732,7 @@ z.nullable(z.string());
|
|
|
1710
1732
|
|
|
1711
1733
|
### `.nullish`
|
|
1712
1734
|
|
|
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" [
|
|
1735
|
+
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).
|
|
1714
1736
|
|
|
1715
1737
|
```ts
|
|
1716
1738
|
const nullishString = z.string().nullish(); // string | null | undefined
|
|
@@ -1763,9 +1785,9 @@ z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: st
|
|
|
1763
1785
|
z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
|
1764
1786
|
```
|
|
1765
1787
|
|
|
1766
|
-
|
|
1788
|
+
## Guides and concepts
|
|
1767
1789
|
|
|
1768
|
-
|
|
1790
|
+
### Type inference
|
|
1769
1791
|
|
|
1770
1792
|
You can extract the TypeScript type of any schema with `z.infer<typeof mySchema>` .
|
|
1771
1793
|
|
|
@@ -1777,7 +1799,7 @@ const u: A = 12; // TypeError
|
|
|
1777
1799
|
const u: A = "asdf"; // compiles
|
|
1778
1800
|
```
|
|
1779
1801
|
|
|
1780
|
-
|
|
1802
|
+
**What about transforms?**
|
|
1781
1803
|
|
|
1782
1804
|
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`.
|
|
1783
1805
|
|
|
@@ -1794,7 +1816,7 @@ type output = z.output<typeof stringToNumber>; // number
|
|
|
1794
1816
|
type inferred = z.infer<typeof stringToNumber>; // number
|
|
1795
1817
|
```
|
|
1796
1818
|
|
|
1797
|
-
|
|
1819
|
+
### Writing generic functions
|
|
1798
1820
|
|
|
1799
1821
|
When attempting to write a functions that accepts a Zod schemas as an input, it's common to try something like this:
|
|
1800
1822
|
|
|
@@ -1828,13 +1850,13 @@ const arg = makeSchemaOptional(z.string());
|
|
|
1828
1850
|
arg.unwrap(); // ZodString
|
|
1829
1851
|
```
|
|
1830
1852
|
|
|
1831
|
-
|
|
1853
|
+
#### Constraining allowable inputs
|
|
1832
1854
|
|
|
1833
1855
|
The `ZodType` class has three generic parameters.
|
|
1834
1856
|
|
|
1835
1857
|
```ts
|
|
1836
1858
|
class ZodType<
|
|
1837
|
-
Output,
|
|
1859
|
+
Output = any,
|
|
1838
1860
|
Def extends ZodTypeDef = ZodTypeDef,
|
|
1839
1861
|
Input = Output
|
|
1840
1862
|
> { ... }
|
|
@@ -1854,12 +1876,16 @@ makeSchemaOptional(z.number());
|
|
|
1854
1876
|
// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType<string, ZodTypeDef, string>'
|
|
1855
1877
|
```
|
|
1856
1878
|
|
|
1857
|
-
|
|
1879
|
+
### Error handling
|
|
1858
1880
|
|
|
1859
1881
|
Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.
|
|
1860
1882
|
|
|
1861
1883
|
```ts
|
|
1862
|
-
const data = z
|
|
1884
|
+
const data = z
|
|
1885
|
+
.object({
|
|
1886
|
+
name: z.string(),
|
|
1887
|
+
})
|
|
1888
|
+
.safeParse({ name: 12 });
|
|
1863
1889
|
|
|
1864
1890
|
if (!data.success) {
|
|
1865
1891
|
data.error.issues;
|
|
@@ -1875,20 +1901,31 @@ if (!data.success) {
|
|
|
1875
1901
|
}
|
|
1876
1902
|
```
|
|
1877
1903
|
|
|
1878
|
-
|
|
1904
|
+
> 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)
|
|
1905
|
+
|
|
1906
|
+
### Error formatting
|
|
1879
1907
|
|
|
1880
1908
|
You can use the `.format()` method to convert this error into a nested object.
|
|
1881
1909
|
|
|
1882
1910
|
```ts
|
|
1883
|
-
data
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1911
|
+
const data = z
|
|
1912
|
+
.object({
|
|
1913
|
+
name: z.string(),
|
|
1914
|
+
})
|
|
1915
|
+
.safeParse({ name: 12 });
|
|
1888
1916
|
|
|
1889
|
-
|
|
1917
|
+
if (!data.success) {
|
|
1918
|
+
const formatted = data.error.format();
|
|
1919
|
+
/* {
|
|
1920
|
+
name: { _errors: [ 'Expected string, received number' ] }
|
|
1921
|
+
} */
|
|
1890
1922
|
|
|
1891
|
-
|
|
1923
|
+
formatted.name?._errors;
|
|
1924
|
+
// => ["Expected string, received number"]
|
|
1925
|
+
}
|
|
1926
|
+
```
|
|
1927
|
+
|
|
1928
|
+
## Comparison
|
|
1892
1929
|
|
|
1893
1930
|
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.
|
|
1894
1931
|
|
|
@@ -1940,20 +1977,18 @@ Branded -->
|
|
|
1940
1977
|
* Missing support for parsing cyclical data (maybe)
|
|
1941
1978
|
* Missing error customization -->
|
|
1942
1979
|
|
|
1943
|
-
|
|
1980
|
+
**Joi**
|
|
1944
1981
|
|
|
1945
1982
|
[https://github.com/hapijs/joi](https://github.com/hapijs/joi)
|
|
1946
1983
|
|
|
1947
1984
|
Doesn't support static type inference 😕
|
|
1948
1985
|
|
|
1949
|
-
|
|
1986
|
+
**Yup**
|
|
1950
1987
|
|
|
1951
1988
|
[https://github.com/jquense/yup](https://github.com/jquense/yup)
|
|
1952
1989
|
|
|
1953
1990
|
Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.
|
|
1954
1991
|
|
|
1955
|
-
Differences
|
|
1956
|
-
|
|
1957
1992
|
- Supports casting and transforms
|
|
1958
1993
|
- All object fields are optional by default
|
|
1959
1994
|
- Missing object methods: (partial, deepPartial)
|
|
@@ -1964,7 +1999,7 @@ Differences
|
|
|
1964
1999
|
|
|
1965
2000
|
<!-- ¹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. -->
|
|
1966
2001
|
|
|
1967
|
-
|
|
2002
|
+
**io-ts**
|
|
1968
2003
|
|
|
1969
2004
|
[https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)
|
|
1970
2005
|
|
|
@@ -2015,7 +2050,7 @@ This more declarative API makes schema definitions vastly more concise.
|
|
|
2015
2050
|
- Missing promise schemas
|
|
2016
2051
|
- Missing function schemas
|
|
2017
2052
|
|
|
2018
|
-
|
|
2053
|
+
**Runtypes**
|
|
2019
2054
|
|
|
2020
2055
|
[https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
|
|
2021
2056
|
|
|
@@ -2028,7 +2063,7 @@ Good type inference support, but limited options for object type masking (no `.p
|
|
|
2028
2063
|
- Missing promise schemas
|
|
2029
2064
|
- Missing error customization
|
|
2030
2065
|
|
|
2031
|
-
|
|
2066
|
+
**Ow**
|
|
2032
2067
|
|
|
2033
2068
|
[https://github.com/sindresorhus/ow](https://github.com/sindresorhus/ow)
|
|
2034
2069
|
|
|
@@ -2036,6 +2071,6 @@ Ow is focused on function input validation. It's a library that makes it easy to
|
|
|
2036
2071
|
|
|
2037
2072
|
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.
|
|
2038
2073
|
|
|
2039
|
-
|
|
2074
|
+
## Changelog
|
|
2040
2075
|
|
|
2041
2076
|
View the changelog at [CHANGELOG.md](CHANGELOG.md)
|