zod 4.0.0-beta.1 โ†’ 4.0.0-beta.20250410T035006

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.
Files changed (102) hide show
  1. package/LICENSE +1 -1
  2. package/dist/commonjs/checks.d.ts +1 -0
  3. package/dist/commonjs/checks.js +32 -0
  4. package/dist/commonjs/coerce.d.ts +17 -0
  5. package/dist/commonjs/coerce.js +57 -0
  6. package/dist/commonjs/compat.d.ts +47 -0
  7. package/dist/commonjs/compat.js +73 -0
  8. package/dist/commonjs/errors.d.ts +29 -0
  9. package/dist/commonjs/errors.js +61 -0
  10. package/dist/commonjs/external.d.ts +8 -0
  11. package/dist/commonjs/external.js +67 -0
  12. package/dist/commonjs/index.d.ts +4 -0
  13. package/dist/commonjs/index.js +43 -0
  14. package/dist/commonjs/iso.d.ts +22 -0
  15. package/dist/commonjs/iso.js +70 -0
  16. package/dist/commonjs/package.json +3 -0
  17. package/dist/commonjs/parse.d.ts +17 -0
  18. package/dist/commonjs/parse.js +44 -0
  19. package/dist/commonjs/schemas.d.ts +750 -0
  20. package/dist/commonjs/schemas.js +1190 -0
  21. package/dist/esm/checks.d.ts +1 -0
  22. package/dist/esm/checks.js +1 -0
  23. package/dist/esm/coerce.d.ts +17 -0
  24. package/dist/esm/coerce.js +17 -0
  25. package/dist/esm/compat.d.ts +47 -0
  26. package/dist/esm/compat.js +33 -0
  27. package/dist/esm/errors.d.ts +29 -0
  28. package/dist/esm/errors.js +24 -0
  29. package/dist/esm/external.d.ts +8 -0
  30. package/dist/esm/external.js +14 -0
  31. package/dist/esm/index.d.ts +4 -0
  32. package/dist/esm/index.js +4 -0
  33. package/dist/esm/iso.d.ts +22 -0
  34. package/dist/esm/iso.js +30 -0
  35. package/dist/esm/package.json +3 -0
  36. package/dist/esm/parse.d.ts +17 -0
  37. package/dist/esm/parse.js +8 -0
  38. package/dist/esm/schemas.d.ts +750 -0
  39. package/dist/esm/schemas.js +1074 -0
  40. package/package.json +66 -82
  41. package/src/checks.ts +30 -0
  42. package/src/coerce.ts +27 -0
  43. package/src/compat.ts +74 -0
  44. package/src/errors.ts +50 -0
  45. package/src/external.ts +29 -0
  46. package/src/index.ts +5 -0
  47. package/src/iso.ts +90 -0
  48. package/src/parse.ts +32 -0
  49. package/src/schemas.ts +2360 -0
  50. package/CHANGELOG.md +0 -160
  51. package/README.md +0 -1730
  52. package/lib/.DS_Store +0 -0
  53. package/lib/PseudoPromise.d.ts +0 -7
  54. package/lib/PseudoPromise.d.ts.map +0 -1
  55. package/lib/PseudoPromise.js +0 -17
  56. package/lib/PseudoPromise.js.map +0 -1
  57. package/lib/ZodError.d.ts +0 -137
  58. package/lib/ZodError.d.ts.map +0 -1
  59. package/lib/ZodError.js +0 -301
  60. package/lib/ZodError.js.map +0 -1
  61. package/lib/benchmarks/index.d.ts +0 -2
  62. package/lib/benchmarks/index.d.ts.map +0 -1
  63. package/lib/benchmarks/index.js +0 -54
  64. package/lib/benchmarks/index.js.map +0 -1
  65. package/lib/benchmarks/object.d.ts +0 -6
  66. package/lib/benchmarks/object.d.ts.map +0 -1
  67. package/lib/benchmarks/object.js +0 -71
  68. package/lib/benchmarks/object.js.map +0 -1
  69. package/lib/benchmarks/string.d.ts +0 -6
  70. package/lib/benchmarks/string.d.ts.map +0 -1
  71. package/lib/benchmarks/string.js +0 -45
  72. package/lib/benchmarks/string.js.map +0 -1
  73. package/lib/external.d.ts +0 -4
  74. package/lib/external.d.ts.map +0 -1
  75. package/lib/external.js +0 -16
  76. package/lib/external.js.map +0 -1
  77. package/lib/helpers/errorUtil.d.ts +0 -10
  78. package/lib/helpers/errorUtil.d.ts.map +0 -1
  79. package/lib/helpers/errorUtil.js +0 -13
  80. package/lib/helpers/errorUtil.js.map +0 -1
  81. package/lib/helpers/parseUtil.d.ts +0 -74
  82. package/lib/helpers/parseUtil.d.ts.map +0 -1
  83. package/lib/helpers/parseUtil.js +0 -179
  84. package/lib/helpers/parseUtil.js.map +0 -1
  85. package/lib/helpers/partialUtil.d.ts +0 -18
  86. package/lib/helpers/partialUtil.d.ts.map +0 -1
  87. package/lib/helpers/partialUtil.js +0 -3
  88. package/lib/helpers/partialUtil.js.map +0 -1
  89. package/lib/helpers/util.d.ts +0 -18
  90. package/lib/helpers/util.d.ts.map +0 -1
  91. package/lib/helpers/util.js +0 -87
  92. package/lib/helpers/util.js.map +0 -1
  93. package/lib/index.d.ts +0 -4
  94. package/lib/index.d.ts.map +0 -1
  95. package/lib/index.js +0 -29
  96. package/lib/index.js.map +0 -1
  97. package/lib/index.mjs +0 -2808
  98. package/lib/index.mjs.map +0 -1
  99. package/lib/types.d.ts +0 -541
  100. package/lib/types.d.ts.map +0 -1
  101. package/lib/types.js +0 -2282
  102. package/lib/types.js.map +0 -1
package/README.md DELETED
@@ -1,1730 +0,0 @@
1
- <p align="center">
2
- <img src="logo.svg" width="200px" align="center" />
3
- <h1 align="center">Zod</h1>
4
- </p>
5
- <p align="center">
6
- <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>
7
- <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a>
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
- <a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a>
10
- <a href="./src/__tests__" rel="nofollow"><img src="./coverage.svg" alt="coverage"></a>
11
-
12
- </p>
13
- <p align="center">
14
- โญ๏ธ smash that star button โญ๏ธ
15
- </p>
16
-
17
- > If you like Zod, you'll love my new library [tRPC](https://trpc.io). It's a way to build end-to-end typesafe APIs without GraphQL or code generation! Check it out at [trpc.io](https://trpc.io).
18
-
19
- <br/>
20
-
21
- ## May 17, 2021: Zod v3 is now in stable release!
22
-
23
- Check out the [Migration Guide](https://github.com/colinhacks/zod/blob/master/MIGRATION.md) to upgrade.
24
-
25
- Previous versions:
26
-
27
- - [`Zod 1 docs`](https://github.com/colinhacks/zod/tree/v1)
28
- - [`Zod 2 docs`](https://github.com/colinhacks/zod/tree/v2)
29
-
30
- #### New features
31
-
32
- - **Easier imports**: you can now import Zod like `import { z } from 'zod';` instead of using `import * as` syntax.
33
- - **Structured error messages**. Use the `.format()` method to ZodError to convert the error into a strongly-typed, nested object: [format method](#error-formatting)
34
- - **Easier unions**. Use the `or` method to ZodType (the base class for all Zod schemas) to easily create union types like `z.string().or(z.number())`
35
- - **Easier intersections**. Use the `and` method to ZodType (the base class for all Zod schemas) to easily create intersection types
36
- - **Global error customization**. Use `z.setErrorMap(myErrorMap)` to _globally_ customize the error messages produced by Zod: [setErrorMap](ERROR_HANDLING.md#customizing-errors-with-zoderrormap)
37
- - **Maps and sets**. Zod now supports [`Map`](#maps) and [`Set`](#set) schemas.
38
- - **Optional and nullable unwrapping**. ZodOptional and ZodNullable now have a `.unwrap()` method for retrieving the schema they wrap.
39
- - **A new implementation of transformers**. See the [Migration Guide](https://github.com/colinhacks/zod/blob/master/MIGRATION.md) section to understand the syntax changes.
40
-
41
- # Table of contents
42
-
43
- - [What is Zod](#what-is-zod)
44
- - [Installation](#installation)
45
- - [Ecosystem](#ecosystem)
46
- - [Basic usage](#basic-usage)
47
- - [Defining schemas](#defining-schemas)
48
- - [Primitives](#primitives)
49
- - [Literals](#literals)
50
- - [Strings](#strings)
51
- - [Numbers](#numbers)
52
- - [Objects](#objects)
53
- - [.shape](#shape)
54
- - [.extend](#extend)
55
- - [.merge](#merge)
56
- - [.pick/.omit](#pickomit)
57
- - [.partial](#partial)
58
- - [.deepPartial](#deepPartial)
59
- - [.passthrough](#passthrough)
60
- - [.strict](#strict)
61
- - [.strip](#strip)
62
- - [.catchall](#catchall)
63
- - [Records](#records)
64
- - [Maps](#maps)
65
- - [Sets](#sets)
66
- - [Arrays](#arrays)
67
- - [.nonempty](#nonempty)
68
- - [.min/.max/.length](#minmaxlength)
69
- - [Unions](#unions)
70
- - [Optionals](#optionals)
71
- - [Nullables](#nullables)
72
- - [Enums](#enums)
73
- - [Zod enums](#zod-enums)
74
- - [Native enums](#native-enums)
75
- - [Tuples](#tuples)
76
- - [Recursive types](#recursive-types)
77
- - [JSON type](#json-type)
78
- - [Cyclical data](#cyclical-objects)
79
- - [Promises](#promises)
80
- - [Instanceof](#instanceof)
81
- - [Function schemas](#function-schemas)
82
- - [Base class methods (ZodType)](#zodtype-methods-and-properties)
83
- - [.parse](#parse)
84
- - [.parseAsync](#parseasync)
85
- - [.safeParse](#safeparse)
86
- - [.safeParseAsync](#safeparseasync)
87
- - [.refine](#refine)
88
- - [.superRefine](#superRefine)
89
- - [.transform](#transform)
90
- - [.default](#default)
91
- - [.optional](#optional)
92
- - [.nullable](#nullable)
93
- - [.nullish](#nullish)
94
- - [.array](#array)
95
- - [.or](#or)
96
- - [.and](#and)
97
- - [Type inference](#type-inference)
98
- - [Errors](#errors)
99
- - [Comparison](#comparison)
100
- - [Joi](#joi)
101
- - [Yup](#yup)
102
- - [io-ts](#io-ts)
103
- - [Runtypes](#runtypes)
104
- - [Changelog](#changelog)
105
-
106
- <!-- **Zod 2 is coming! Follow [@colinhacks](https://twitter.com/colinhacks) to stay updated and discuss the future of Zod.** -->
107
-
108
- # What is Zod
109
-
110
- 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.
111
-
112
- Zod is designed to be as developer-friendly as possible. The goal is to eliminate duplicative type declarations. With Zod, you declare a validator _once_ and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.
113
-
114
- Some other great aspects:
115
-
116
- - Zero dependencies
117
- - Works in browsers and Node.js
118
- - Tiny: 8kb minified + zipped
119
- - Immutable: methods (i.e. `.optional()` return a new instance
120
- - Concise, chainable interface
121
- - Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
122
- - Works with plain JavaScript too! You don't need to use TypeScript.
123
-
124
- # Sponsorship
125
-
126
- Sponsorship at any level is appreciated and encouraged. Zod is maintained by a solo developer ([hi!](https://twitter.com/colinhacks)). For individual developers, consider the [Cup of Coffee tier](https://github.com/sponsors/colinhacks). If you built a paid product using Zod, consider the [Startup tier](https://github.com/sponsors/colinhacks). You can learn more about the tiers at [github.com/sponsors/colinhacks](https://github.com/sponsors/colinhacks).
127
-
128
- ### Sponsors
129
-
130
- <table>
131
- <tr>
132
- <td align="center">
133
- <a href="https://deletype.com/">
134
- <img src="https://avatars0.githubusercontent.com/u/15068039?s=200&v=4" width="100px;" alt="" />
135
- </a>
136
- <br>
137
- <b>Deletype</b>
138
- <br>
139
- <a href="https://deletype.com/">https://deletype.com/</a>
140
- </td>
141
- <td align="center">
142
- <a href="https://github.com/kevinsimper">
143
- <img src="https://avatars1.githubusercontent.com/u/1126497?s=460&v=4" width="100px;" alt="" />
144
- </a>
145
- <br>
146
- <b>Kevin Simper</b>
147
- <br>
148
- <a href="https://github.com/kevinsimper">@kevinsimper</a>
149
- </td>
150
- <td align="center">
151
- <a href="https://twitter.com/flybayer">
152
- <img src="https://avatars2.githubusercontent.com/u/8813276?s=460&u=4ff8beb9a67b173015c4b426a92d89cab960af1b&v=4" width="100px;" alt=""/>
153
- </a>
154
- <br>
155
- <b>Brandon Bayer</b>
156
- <br/>
157
- <a href="https://twitter.com/flybayer">@flybayer</a>,
158
- <span>creator of <a href="https://blitzjs.com">Blitz.js</a></span>
159
- <br />
160
- </td>
161
-
162
- </tr>
163
- <tr>
164
- <td align="center">
165
- <a href="https://www.bamboocreative.nz/">
166
- <img src="https://avatars1.githubusercontent.com/u/41406870?s=460&v=4" width="100px;" alt="" />
167
- </a>
168
- <br>
169
- <b>Bamboo Creative</b>
170
- <br>
171
- <a href="https://www.bamboocreative.nz/">https://bamboocreative.nz</a>
172
- </td>
173
- <td align="center">
174
- <a href="https://github.com/jeremyBanks">
175
- <img src="https://avatars.githubusercontent.com/u/18020?s=400&u=dba6c1402ae1746a276a5d256e01d68e774a0e9d&v=4" width="100px;" alt="" />
176
- </a>
177
- <br>
178
- <b>Jeremy Banks</b>
179
- <br>
180
- <a href="https://github.com/jeremyBanks">github.com/jeremyBanks</a>
181
- </td>
182
- <td align="center">
183
- <a href="https://marcatopartners.com/">
184
- <img src="https://avatars.githubusercontent.com/u/84106192?s=200&v=4" width="100px;" alt="Marcato Partners" />
185
- </a>
186
- <br>
187
- <b>Marcato Partners</b>
188
- <br>
189
- <a href="https://marcatopartners.com/">marcatopartners.com</a>
190
- </td>
191
- </tr>
192
- </table>
193
-
194
- _To get your name + Twitter + website here, sponsor Zod at the [Freelancer](https://github.com/sponsors/colinhacks) or [Consultancy](https://github.com/sponsors/colinhacks) tier._
195
-
196
- # Installation
197
-
198
- To install Zod v3:
199
-
200
- ```sh
201
- npm install zod
202
- ```
203
-
204
- โš ๏ธ IMPORTANT: You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects.
205
-
206
- ```ts
207
- // tsconfig.json
208
- {
209
- // ...
210
- "compilerOptions": {
211
- // ...
212
- "strict": true
213
- }
214
- }
215
- ```
216
-
217
- #### TypeScript requirements
218
-
219
- - Zod 3.x requires TypeScript 4.1+
220
- - Zod 2.x requires TypeScript 3.7+
221
- - Zod 1.x requires TypeScript 3.3+
222
-
223
- # Ecosystem
224
-
225
- 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.
226
-
227
- - [`tRPC`](https://github.com/trpc/trpc): Build end-to-end typesafe APIs without GraphQL
228
- - [`react-hook-form`](https://github.com/react-hook-form/resolvers): Build type-safe forms easily with React Hook Form and the Zod resolver.
229
- - [`ts-to-zod`](https://github.com/fabien0102/ts-to-zod): Convert TypeScript definitions into Zod schemas.
230
- - [`zod-mocking`](https://github.com/dipasqualew/zod-mocking): Generate mock data from your Zod schemas.
231
- - [`zod-fast-check`](https://github.com/DavidTimms/zod-fast-check): Generate `fast-check` arbitraries from Zod schemas.
232
- - [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
233
- - [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares
234
-
235
- # Basic usage
236
-
237
- Creating a simple string schema
238
-
239
- ```ts
240
- import { z } from "zod";
241
-
242
- // creating a schema for strings
243
- const mySchema = z.string();
244
- mySchema.parse("tuna"); // => "tuna"
245
- mySchema.parse(12); // => throws ZodError
246
- ```
247
-
248
- Creating an object schema
249
-
250
- ```ts
251
- import { z } from "zod";
252
-
253
- const User = z.object({
254
- username: z.string(),
255
- });
256
-
257
- User.parse({ username: string });
258
-
259
- // extract the inferred type
260
- type User = z.infer<typeof User>;
261
- // { username: string }
262
- ```
263
-
264
- # Defining schemas
265
-
266
- ## Primitives
267
-
268
- ```ts
269
- import { z } from "zod";
270
-
271
- // primitive values
272
- z.string();
273
- z.number();
274
- z.bigint();
275
- z.boolean();
276
- z.date();
277
-
278
- // empty types
279
- z.undefined();
280
- z.null();
281
- z.void(); // accepts null or undefined
282
-
283
- // catch-all types
284
- // allows any value
285
- z.any();
286
- z.unknown();
287
-
288
- // never type
289
- // allows no values
290
- z.never();
291
- ```
292
-
293
- ## Literals
294
-
295
- ```ts
296
- const tuna = z.literal("tuna");
297
- const twelve = z.literal(12);
298
- const tru = z.literal(true);
299
- ```
300
-
301
- > Currently there is no support for Date or bigint literals in Zod. If you have a use case for this feature, please file an issue.
302
-
303
- ## Strings
304
-
305
- Zod includes a handful of string-specific validations.
306
-
307
- ```ts
308
- z.string().max(5);
309
- z.string().min(5);
310
- z.string().length(5);
311
- z.string().email();
312
- z.string().url();
313
- z.string().uuid();
314
- z.string().regex(regex);
315
-
316
- // deprecated, equivalent to .min(1)
317
- z.string().nonempty();
318
- ```
319
-
320
- > Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
321
-
322
- #### Custom error messages
323
-
324
- Optionally, you can pass in a second argument to provide a custom error message.
325
-
326
- ```ts
327
- z.string().min(5, { message: "Must be 5 or more characters long" });
328
- z.string().max(5, { message: "Must be 5 or fewer characters long" });
329
- z.string().length(5, { message: "Must be exactly 5 characters long" });
330
- z.string().email({ message: "Invalid email address." });
331
- z.string().url({ message: "Invalid url" });
332
- z.string().uuid({ message: "Invalid UUID" });
333
- ```
334
-
335
- ## Numbers
336
-
337
- Zod includes a handful of number-specific validations.
338
-
339
- ```ts
340
- z.number().min(5);
341
- z.number().max(5);
342
-
343
- z.number().int(); // value must be an integer
344
-
345
- z.number().positive(); // > 0
346
- z.number().nonnegative(); // >= 0
347
- z.number().negative(); // < 0
348
- z.number().nonpositive(); // <= 0
349
- ```
350
-
351
- Optionally, you can pass in a second argument to provide a custom error message.
352
-
353
- ```ts
354
- z.number().max(5, { message: "this๐Ÿ‘is๐Ÿ‘too๐Ÿ‘big" });
355
- ```
356
-
357
- ## Objects
358
-
359
- ```ts
360
- // all properties are required by default
361
- const Dog = z.object({
362
- name: z.string(),
363
- age: z.number(),
364
- });
365
-
366
- // extract the inferred type like this
367
- type Dog = z.infer<typeof Dog>;
368
-
369
- // equivalent to:
370
- type Dog = {
371
- name: string;
372
- age: number;
373
- };
374
- ```
375
-
376
- ### `.shape`
377
-
378
- Use `.shape` to access the schemas for a particular key.
379
-
380
- ```ts
381
- Dog.shape.name; // => string schema
382
- Dog.shape.age; // => number schema
383
- ```
384
-
385
- ### `.extend`
386
-
387
- You can add additional fields an object schema with the `.extend` method.
388
-
389
- ```ts
390
- const DogWithBreed = Dog.extend({
391
- breed: z.string(),
392
- });
393
- ```
394
-
395
- You can use `.extend` to overwrite fields! Be careful with this power!
396
-
397
- ### `.merge`
398
-
399
- Equivalent to `A.extend(B.shape)`.
400
-
401
- ```ts
402
- const BaseTeacher = z.object({ students: z.array(z.string()) });
403
- const HasID = z.object({ id: z.string() });
404
-
405
- const Teacher = BaseTeacher.merge(HasID);
406
- type Teacher = z.infer<typeof Teacher>; // => { students: string[], id: string }
407
- ```
408
-
409
- > If the two schemas share keys, the properties of B overrides the property of A. The returned schema also inherits the "unknownKeys" policy (strip/strict/passthrough) and the catchall schema of B.
410
-
411
- ### `.pick/.omit`
412
-
413
- Inspired by TypeScript's built-in `Pick` and `Omit` utility types, all Zod object schemas have `.pick` and `.omit` methods that return a modified version. Consider this Recipe schema:
414
-
415
- ```ts
416
- const Recipe = z.object({
417
- id: z.string(),
418
- name: z.string(),
419
- ingredients: z.array(z.string()),
420
- });
421
- ```
422
-
423
- To only keep certain keys, use `.pick` .
424
-
425
- ```ts
426
- const JustTheName = Recipe.pick({ name: true });
427
- type JustTheName = z.infer<typeof JustTheName>;
428
- // => { name: string }
429
- ```
430
-
431
- To remove certain keys, use `.omit` .
432
-
433
- ```ts
434
- const NoIDRecipe = Recipe.omit({ id: true });
435
-
436
- type NoIDRecipe = z.infer<typeof NoIDRecipe>;
437
- // => { name: string, ingredients: string[] }
438
- ```
439
-
440
- ### `.partial`
441
-
442
- Inspired by the built-in TypeScript utility type [Partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialt), the `.partial` method makes all properties optional.
443
-
444
- Starting from this object:
445
-
446
- ```ts
447
- const user = z.object({
448
- username: z.string(),
449
- });
450
- // { username: string }
451
- ```
452
-
453
- We can create a partial version:
454
-
455
- ```ts
456
- const partialUser = user.partial();
457
- // { username?: string | undefined }
458
- ```
459
-
460
- ### `.deepPartial`
461
-
462
- The `.partial` method is shallow โ€” it only applies one level deep. There is also a "deep" version:
463
-
464
- ```ts
465
- const user = z.object({
466
- username: z.string(),
467
- location: z.object({
468
- latitude: z.number(),
469
- longitude: z.number(),
470
- }),
471
- });
472
-
473
- const deepPartialUser = user.deepPartial();
474
-
475
- /*
476
- {
477
- username?: string | undefined,
478
- location?: {
479
- latitude?: number | undefined;
480
- longitude?: number | undefined;
481
- } | undefined
482
- }
483
- */
484
- ```
485
-
486
- > Important limitation: deep partials only work as expected in direct hierarchies of object schemas. A nested object schema can't be optional, nullable, contain refinements, contain transforms, etc.
487
-
488
- #### Unrecognized keys
489
-
490
- By default Zod objects schemas strip out unrecognized keys during parsing.
491
-
492
- ```ts
493
- const person = z.object({
494
- name: z.string(),
495
- });
496
-
497
- person.parse({
498
- name: "bob dylan",
499
- extraKey: 61,
500
- });
501
- // => { name: "bob dylan" }
502
- // extraKey has been stripped
503
- ```
504
-
505
- ### `.passthrough`
506
-
507
- Instead, if you want to pass through unknown keys, use `.passthrough()` .
508
-
509
- ```ts
510
- person.passthrough().parse({
511
- name: "bob dylan",
512
- extraKey: 61,
513
- });
514
- // => { name: "bob dylan", extraKey: 61 }
515
- ```
516
-
517
- ### `.strict`
518
-
519
- You can _disallow_ unknown keys with `.strict()` . If there are any unknown keys in the input, Zod will throw an error.
520
-
521
- ```ts
522
- const person = z
523
- .object({
524
- name: z.string(),
525
- })
526
- .strict();
527
-
528
- person.parse({
529
- name: "bob dylan",
530
- extraKey: 61,
531
- });
532
- // => throws ZodError
533
- ```
534
-
535
- ### `.strip`
536
-
537
- You can use the `.strip` method to reset an object schema to the default behavior (stripping unrecognized keys).
538
-
539
- ### `.catchall`
540
-
541
- You can pass a "catchall" schema into an object schema. All unknown keys will be validated against it.
542
-
543
- ```ts
544
- const person = z
545
- .object({
546
- name: z.string(),
547
- })
548
- .catchall(z.number());
549
-
550
- person.parse({
551
- name: "bob dylan",
552
- validExtraKey: 61, // works fine
553
- });
554
-
555
- person.parse({
556
- name: "bob dylan",
557
- validExtraKey: false, // fails
558
- });
559
- // => throws ZodError
560
- ```
561
-
562
- Using `.catchall()` obviates `.passthrough()` , `.strip()` , or `.strict()`. All keys are now considered "known".
563
-
564
- ## Arrays
565
-
566
- ```ts
567
- const stringArray = z.array(z.string());
568
-
569
- // equivalent
570
- const stringArray = z.string().array();
571
- ```
572
-
573
- Be careful with the `.array()` method. It returns a new `ZodArray` instance. This means the _order_ in which you call methods matters. For instance:
574
-
575
- ```ts
576
- z.string().optional().array(); // (string | undefined)[]
577
- z.string().array().optional(); // string[] | undefined
578
- ```
579
-
580
- ### `.nonempty`
581
-
582
- If you want to ensure that an array contains at least one element, use `.nonempty()`.
583
-
584
- ```ts
585
- const nonEmptyStrings = z.string().array().nonempty();
586
- // the inferred type is now
587
- // [string, ...string[]]
588
-
589
- nonEmptyStrings.parse([]); // throws: "Array cannot be empty"
590
- nonEmptyStrings.parse(["Ariana Grande"]); // passes
591
- ```
592
-
593
- ### `.min/.max/.length`
594
-
595
- ```ts
596
- z.string().array().min(5); // must contain 5 or more items
597
- z.string().array().max(5); // must contain 5 or fewer items
598
- z.string().array().length(5); // must contain 5 items exactly
599
- ```
600
-
601
- Unlike `.nonempty()` these methods do not change the inferred type.
602
-
603
- ## Unions
604
-
605
- Zod includes a built-in `z.union` method for composing "OR" types.
606
-
607
- ```ts
608
- const stringOrNumber = z.union([z.string(), z.number()]);
609
-
610
- stringOrNumber.parse("foo"); // passes
611
- stringOrNumber.parse(14); // passes
612
- ```
613
-
614
- Zod will test the input against each of the "options" in order and return the first value that validates successfully.
615
-
616
- For convenience, you can also use the `.or` method:
617
-
618
- ```ts
619
- const stringOrNumber = z.string().or(z.number());
620
- ```
621
-
622
- ## Optionals
623
-
624
- You can make any schema optional with `z.optional()`:
625
-
626
- ```ts
627
- const schema = z.optional(z.string());
628
-
629
- schema.parse(undefined); // => returns undefined
630
- type A = z.infer<typeof A>; // string | undefined
631
- ```
632
-
633
- You can make an existing schema optional with the `.optional()` method:
634
-
635
- ```ts
636
- const user = z.object({
637
- username: z.string().optional(),
638
- });
639
- type C = z.infer<typeof C>; // { username?: string | undefined };
640
- ```
641
-
642
- #### `.unwrap`
643
-
644
- ```ts
645
- const stringSchema = z.string();
646
- const optionalString = stringSchema.optional();
647
- optionalString.unwrap() === stringSchema; // true
648
- ```
649
-
650
- ## Nullables
651
-
652
- Similarly, you can create nullable types like so:
653
-
654
- ```ts
655
- const nullableString = z.nullable(z.string());
656
- nullableString.parse("asdf"); // => "asdf"
657
- nullableString.parse(null); // => null
658
- ```
659
-
660
- You can make an existing schema nullable with the `nullable` method:
661
-
662
- ```ts
663
- const E = z.string().nullable(); // equivalent to D
664
- type E = z.infer<typeof D>; // string | null
665
- ```
666
-
667
- #### `.unwrap`
668
-
669
- ```ts
670
- const stringSchema = z.string();
671
- const nullableString = stringSchema.nullable();
672
- nullableString.unwrap() === stringSchema; // true
673
- ```
674
-
675
- <!--
676
-
677
- ``` ts
678
- /* Custom Union Types */
679
-
680
- const F = z
681
- .union([z.string(), z.number(), z.boolean()])
682
- .optional()
683
- .nullable();
684
-
685
- F.parse('tuna'); // => tuna
686
- F.parse(42); // => 42
687
- F.parse(true); // => true
688
- F.parse(undefined); // => undefined
689
- F.parse(null); // => null
690
- F.parse({}); // => throws Error!
691
-
692
- type F = z.infer<typeof F>; // string | number | boolean | undefined | null;
693
- ``` -->
694
-
695
- ## Records
696
-
697
- Record schemas are used to validate types such as `{ [k: string]: number }`.
698
-
699
- If you want to validate the _values_ of an object against some schema but don't care about the keys, use `Record`.
700
-
701
- ```ts
702
- const NumberCache = z.record(z.number());
703
-
704
- type NumberCache = z.infer<typeof NumberCache>;
705
- // => { [k: string]: number }
706
- ```
707
-
708
- This is particularly useful for storing or caching items by ID.
709
-
710
- ```ts
711
- const userStore: UserStore = {};
712
-
713
- userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
714
- name: "Carlotta",
715
- }; // passes
716
-
717
- userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
718
- whatever: "Ice cream sundae",
719
- }; // TypeError
720
- ```
721
-
722
- #### A note on numerical keys
723
-
724
- 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?
725
-
726
- As it turns out, TypeScript's behavior surrounding `[k: number]` is a little unintuitive:
727
-
728
- ```ts
729
- const testMap: { [k: number]: string } = {
730
- 1: "one",
731
- };
732
-
733
- for (const key in testMap) {
734
- console.log(`${key}: ${typeof key}`);
735
- }
736
- // prints: `1: string`
737
- ```
738
-
739
- As you can see, JavaScript automatically casts all object keys to strings under the hood.
740
-
741
- 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.
742
-
743
- ## Maps
744
-
745
- ```ts
746
- const stringNumberMap = z.map(z.string(), z.number());
747
-
748
- type StringNumberMap = z.infer<typeof stringNumberMap>;
749
- // type StringNumber = Map<string, number>
750
- ```
751
-
752
- ## Sets
753
-
754
- ```ts
755
- const numberSet = z.set(z.string());
756
- type numberSet = z.infer<typeof numberSet>;
757
- // Set<number>
758
- ```
759
-
760
- ## Enums
761
-
762
- There are two ways to define enums in Zod.
763
-
764
- ### Zod enums
765
-
766
- <!-- An enum is just a union of string literals, so you _could_ define an enum like this:
767
-
768
- ```ts
769
- const FishEnum = z.union([
770
- z.literal("Salmon"),
771
- z.literal("Tuna"),
772
- z.literal("Trout"),
773
- ]);
774
-
775
- FishEnum.parse("Salmon"); // => "Salmon"
776
- FishEnum.parse("Flounder"); // => throws
777
- ```
778
-
779
- For convenience Zod provides a built-in `z.enum()` function. Here's is the equivalent code: -->
780
-
781
- ```ts
782
- const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]);
783
- type FishEnum = z.infer<typeof FishEnum>;
784
- // 'Salmon' | 'Tuna' | 'Trout'
785
- ```
786
-
787
- You must pass the array of values directly into `z.enum()`. This does not work:
788
-
789
- ```ts
790
- const fish = ["Salmon", "Tuna", "Trout"];
791
- const FishEnum = z.enum(fish);
792
- ```
793
-
794
- In that case, Zod isn't able to infer the individual enum elements; instead the inferred type will be `string` instead of `'Salmon' | 'Tuna' | 'Trout'`
795
-
796
- **Autocompletion**
797
-
798
- To get autocompletion with a Zod enum, use the `.enum` property of your schema:
799
-
800
- ```ts
801
- FishEnum.enum.Salmon; // => autocompletes
802
-
803
- FishEnum.enum;
804
- /*
805
- => {
806
- Salmon: "Salmon",
807
- Tuna: "Tuna",
808
- Trout: "Trout",
809
- }
810
- */
811
- ```
812
-
813
- You can also retrieve the list of options as a tuple with the `.options` property:
814
-
815
- ```ts
816
- FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
817
- ```
818
-
819
- ### Native enums
820
-
821
- 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()` .
822
-
823
- **Numeric enums**
824
-
825
- ```ts
826
- enum Fruits {
827
- Apple,
828
- Banana,
829
- }
830
-
831
- const FruitEnum = z.nativeEnum(Fruits);
832
- type FruitEnum = z.infer<typeof FruitEnum>; // Fruits
833
-
834
- FruitEnum.parse(Fruits.Apple); // passes
835
- FruitEnum.parse(Fruits.Banana); // passes
836
- FruitEnum.parse(0); // passes
837
- FruitEnum.parse(1); // passes
838
- FruitEnum.parse(3); // fails
839
- ```
840
-
841
- **String enums**
842
-
843
- ```ts
844
- enum Fruits {
845
- Apple = "apple",
846
- Banana = "banana",
847
- Cantaloupe, // you can mix numerical and string enums
848
- }
849
-
850
- const FruitEnum = z.nativeEnum(Fruits);
851
- type FruitEnum = z.infer<typeof FruitEnum>; // Fruits
852
-
853
- FruitEnum.parse(Fruits.Apple); // passes
854
- FruitEnum.parse(Fruits.Cantaloupe); // passes
855
- FruitEnum.parse("apple"); // passes
856
- FruitEnum.parse("banana"); // passes
857
- FruitEnum.parse(0); // passes
858
- FruitEnum.parse("Cantaloupe"); // fails
859
- ```
860
-
861
- **Const enums**
862
-
863
- The `.nativeEnum()` function works for `as const` objects as well. โš ๏ธ `as const` required TypeScript 3.4+!
864
-
865
- ```ts
866
- const Fruits = {
867
- Apple: "apple",
868
- Banana: "banana",
869
- Cantaloupe: 3,
870
- } as const;
871
-
872
- const FruitEnum = z.nativeEnum(Fruits);
873
- type FruitEnum = z.infer<typeof FruitEnum>; // "apple" | "banana" | 3
874
-
875
- FruitEnum.parse("apple"); // passes
876
- FruitEnum.parse("banana"); // passes
877
- FruitEnum.parse(3); // passes
878
- FruitEnum.parse("Cantaloupe"); // fails
879
- ```
880
-
881
- ## Intersections
882
-
883
- <!-- > โš ๏ธ Intersections are deprecated. If you are trying to merge objects, use the `.merge` method instead. -->
884
-
885
- Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.
886
-
887
- ```ts
888
- const Person = z.object({
889
- name: z.string(),
890
- });
891
-
892
- const Employee = z.object({
893
- role: z.string(),
894
- });
895
-
896
- const EmployedPerson = z.intersection(Person, Employee);
897
-
898
- // equivalent to:
899
- const EmployedPerson = Person.and(Employee);
900
- ```
901
-
902
- Though in many cases, it is recommended to use `A.merge(B)` to merge two objects. The `.merge` method returns a new `ZodObject` instance, whereas `A.and(B)` returns a less useful `ZodIntersection` instance that lacks common object methods like `pick` and `omit`.
903
-
904
- ```ts
905
- const a = z.union([z.number(), z.string()]);
906
- const b = z.union([z.number(), z.boolean()]);
907
- const c = z.intersection(a, b);
908
-
909
- type c = z.infer<typeof c>; // => number
910
- ```
911
-
912
- <!-- Intersections in Zod are not smart. Whatever data you pass into `.parse()` gets passed into the two intersected schemas. Because Zod object schemas don't allow any unknown keys by default, there are some unintuitive behavior surrounding intersections of object schemas. -->
913
-
914
- <!--
915
-
916
- ``` ts
917
- const A = z.object({
918
- a: z.string(),
919
- });
920
-
921
- const B = z.object({
922
- b: z.string(),
923
- });
924
-
925
- const AB = z.intersection(A, B);
926
-
927
- type Teacher = z.infer<typeof Teacher>;
928
- // { id:string; name:string };
929
- ``` -->
930
-
931
- ## Tuples
932
-
933
- Unlike arrays, tuples have a fixed number of elements and each element can have a different type.
934
-
935
- ```ts
936
- const athleteSchema = z.tuple([
937
- z.string(), // name
938
- z.number(), // jersey number
939
- z.object({
940
- pointsScored: z.number(),
941
- }), // statistics
942
- ]);
943
-
944
- type Athlete = z.infer<typeof athleteSchema>;
945
- // type Athlete = [string, number, { pointsScored: number }]
946
- ```
947
-
948
- ## Recursive types
949
-
950
- You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".
951
-
952
- ```ts
953
- interface Category {
954
- name: string;
955
- subcategories: Category[];
956
- }
957
-
958
- // cast to z.ZodSchema<Category>
959
- const Category: z.ZodSchema<Category> = z.lazy(() =>
960
- z.object({
961
- name: z.string(),
962
- subcategories: z.array(Category),
963
- })
964
- );
965
-
966
- Category.parse({
967
- name: "People",
968
- subcategories: [
969
- {
970
- name: "Politicians",
971
- subcategories: [{ name: "Presidents", subcategories: [] }],
972
- },
973
- ],
974
- }); // passes
975
- ```
976
-
977
- Unfortunately this code is a bit duplicative, since you're declaring the types twice: once in the interface and again in the Zod definition.
978
-
979
- <!-- If your schema has lots of primitive fields, there's a way of reducing the amount of duplication:
980
-
981
- ```ts
982
- // define all the non-recursive stuff here
983
- const BaseCategory = z.object({
984
- name: z.string(),
985
- tags: z.array(z.string()),
986
- itemCount: z.number(),
987
- });
988
-
989
- // create an interface that extends the base schema
990
- interface Category extends z.infer<typeof BaseCategory> {
991
- subcategories: Category[];
992
- }
993
-
994
- // merge the base schema with
995
- // a new Zod schema containing relations
996
- const Category: z.ZodSchema<Category> = BaseCategory.merge(
997
- z.object({
998
- subcategories: z.lazy(() => z.array(Category)),
999
- })
1000
- );
1001
- ``` -->
1002
-
1003
- #### JSON type
1004
-
1005
- If you want to validate any JSON value, you can use the snippet below.
1006
-
1007
- ```ts
1008
- type Literal = boolean | null | number | string;
1009
- type Json = Literal | { [key: string]: Json } | Json[];
1010
- const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
1011
- const jsonSchema: z.ZodSchema<Json> = z.lazy(() =>
1012
- z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)])
1013
- );
1014
-
1015
- jsonSchema.parse(data);
1016
- ```
1017
-
1018
- Thanks to [ggoodman](https://github.com/ggoodman) for suggesting this.
1019
-
1020
- #### Cyclical objects
1021
-
1022
- Despite supporting recursive schemas, passing an cyclical data into Zod will cause an infinite loop.
1023
-
1024
- ## Promises
1025
-
1026
- ```ts
1027
- const numberPromise = z.promise(z.number());
1028
- ```
1029
-
1030
- "Parsing" works a little differently with promise schemas. Validation happens in two parts:
1031
-
1032
- 1. Zod synchronously checks that the input is an instance of Promise (i.e. an object with `.then` and `.catch` methods.).
1033
- 2. Zod uses `.then` to attach an additional validation step onto the existing Promise. You'll have to use `.catch` on the returned Promise to handle validation failures.
1034
-
1035
- ```ts
1036
- numberPromise.parse("tuna");
1037
- // ZodError: Non-Promise type: string
1038
-
1039
- numberPromise.parse(Promise.resolve("tuna"));
1040
- // => Promise<number>
1041
-
1042
- const test = async () => {
1043
- await numberPromise.parse(Promise.resolve("tuna"));
1044
- // ZodError: Non-number type: string
1045
-
1046
- await numberPromise.parse(Promise.resolve(3.14));
1047
- // => 3.14
1048
- };
1049
- ```
1050
-
1051
- <!-- #### Non-native promise implementations
1052
-
1053
- When "parsing" a promise, Zod checks that the passed value is an object with `.then` and `.catch` methods โ€” that's it. So you should be able to pass non-native Promises (Bluebird, etc) into `z.promise(...).parse` with no trouble. One gotcha: the return type of the parse function will be a _native_ `Promise` , so if you have downstream logic that uses non-standard Promise methods, this won't work. -->
1054
-
1055
- ## Instanceof
1056
-
1057
- You can use `z.instanceof` to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.
1058
-
1059
- ```ts
1060
- class Test {
1061
- name: string;
1062
- }
1063
-
1064
- const TestSchema = z.instanceof(Test);
1065
-
1066
- const blob: any = "whatever";
1067
- TestSchema.parse(new Test()); // passes
1068
- TestSchema.parse("blob"); // throws
1069
- ```
1070
-
1071
- ## Function schemas
1072
-
1073
- Zod also lets you define "function schemas". This makes it easy to validate the inputs and outputs of a function without intermixing your validation code and "business logic".
1074
-
1075
- You can create a function schema with `z.function(args, returnType)` .
1076
-
1077
- ```ts
1078
- const myFunction = z.function();
1079
-
1080
- type myFunction = z.infer<typeof myFunction>;
1081
- // => ()=>unknown
1082
- ```
1083
-
1084
- **Define inputs and output**
1085
-
1086
- ```ts
1087
- const myFunction = z
1088
- .function()
1089
- .args(z.string(), z.number()) // accepts an arbitrary number of arguments
1090
- .returns(z.boolean());
1091
- type myFunction = z.infer<typeof myFunction>;
1092
- // => (arg0: string, arg1: number)=>boolean
1093
- ```
1094
-
1095
- **Extract the input and output schemas**
1096
- You can extract the parameters and return type of a function schema.
1097
-
1098
- ```ts
1099
- myFunction.parameters();
1100
- // => ZodTuple<[ZodString, ZodNumber]>
1101
-
1102
- myFunction.returnType();
1103
- // => ZodBoolean
1104
- ```
1105
-
1106
- <!-- `z.function()` accepts two arguments:
1107
-
1108
- * `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([])`).
1109
- * `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
1110
-
1111
- > 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 function can actually return either undefined or null.)
1112
-
1113
- <!--
1114
-
1115
- ``` ts
1116
- const args = z.tuple([z.string()]);
1117
-
1118
- const returnType = z.number();
1119
-
1120
- const myFunction = z.function(args, returnType);
1121
- type myFunction = z.infer<typeof myFunction>;
1122
- // => (arg0: string)=>number
1123
- ``` -->
1124
-
1125
- Function schemas have an `.implement()` method which accepts a function and returns a new function that automatically validates it's inputs and outputs.
1126
-
1127
- ```ts
1128
- const trimmedLength = z
1129
- .function()
1130
- .args(z.string()) // accepts an arbitrary number of arguments
1131
- .returns(z.number())
1132
- .implement((x) => {
1133
- // TypeScript knows x is a string!
1134
- return x.trim().length;
1135
- });
1136
-
1137
- trimmedLength("sandwich"); // => 8
1138
- trimmedLength(" asdf "); // => 4
1139
- ```
1140
-
1141
- If you only care about validating inputs, that's fine:
1142
-
1143
- ```ts
1144
- const myFunction = z
1145
- .function()
1146
- .args(z.string())
1147
- .implement((arg) => {
1148
- return [arg.length]; //
1149
- });
1150
- myFunction; // (arg: string)=>number[]
1151
- ```
1152
-
1153
- # ZodType: methods and properties
1154
-
1155
- All Zod schemas contain certain methods.
1156
-
1157
- ### `.parse`
1158
-
1159
- `.parse(data:unknown): T`
1160
-
1161
- 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.
1162
-
1163
- > IMPORTANT: In Zod 2 and Zod 1.11+, the value returned by `.parse` is a _deep clone_ of the variable you passed in. This was also the case in zod@1.4 and earlier.
1164
-
1165
- ```ts
1166
- const stringSchema = z.string();
1167
- stringSchema.parse("fish"); // => returns "fish"
1168
- stringSchema.parse(12); // throws Error('Non-string type: number');
1169
- ```
1170
-
1171
- ### `.parseAsync`
1172
-
1173
- `.parseAsync(data:unknown): Promise<T>`
1174
-
1175
- If you use asynchronous [refinements](#refinements) or [transforms](#transformers) (more on those later), you'll need to use `.parseAsync`
1176
-
1177
- ```ts
1178
- const stringSchema = z.string().refine(async (val) => val.length > 20);
1179
- const value = await stringSchema.parseAsync("hello"); // => hello
1180
- ```
1181
-
1182
- ### `.safeParse`
1183
-
1184
- `.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }`
1185
-
1186
- If you don't want Zod to throw errors when validation fails, use `.safeParse`. This method returns an object containing either the successfully parsed data or a ZodError instance containing detailed information about the validation problems.
1187
-
1188
- ```ts
1189
- stringSchema.safeParse(12);
1190
- // => { success: false; error: ZodError }
1191
-
1192
- stringSchema.safeParse("billie");
1193
- // => { success: true; data: 'billie' }
1194
- ```
1195
-
1196
- The result is a _discriminated union_ so you can handle errors very conveniently:
1197
-
1198
- ```ts
1199
- const result = stringSchema.safeParse("billie");
1200
- if (!result.success) {
1201
- // handle error then return
1202
- result.error;
1203
- } else {
1204
- // do something
1205
- result.data;
1206
- }
1207
- ```
1208
-
1209
- ### `.safeParseAsync`
1210
-
1211
- > Alias: `.spa`
1212
-
1213
- An asynchronous version of `safeParse`.
1214
-
1215
- ```ts
1216
- await stringSchema.safeParseAsync("billie");
1217
- ```
1218
-
1219
- For convenience, this has been aliased to `.spa`:
1220
-
1221
- ```ts
1222
- await stringSchema.spa("billie");
1223
- ```
1224
-
1225
- ### `.refine`
1226
-
1227
- `.refine(validator: (data:T)=>any, params?: RefineParams)`
1228
-
1229
- Zod lets you provide custom validation logic via _refinements_. (For advanced features like creating multiple issues and customizing error codes, see [`.superRefine`](#superrefine).)
1230
-
1231
- Zod was designed to mirror TypeScript as closely as possible. But there are many so-called "refinement types" you may wish to check for that can't be represented in TypeScript's type system. For instance: checking that a number is an integer or that a string is a valid email address.
1232
-
1233
- For example, you can define a custom validation check on _any_ Zod schema with `.refine` :
1234
-
1235
- ```ts
1236
- const myString = z.string().refine((val) => val.length <= 255, {
1237
- message: "String can't be more than 255 characters",
1238
- });
1239
- ```
1240
-
1241
- > โš ๏ธ Refinement functions should not throw. Instead they should return a falsy value to signal failure.
1242
-
1243
- #### Arguments
1244
-
1245
- As you can see, `.refine` takes two arguments.
1246
-
1247
- 1. The first is the validation function. This function takes one input (of type `T` โ€” the inferred type of the schema) and returns `any`. Any truthy value will pass validation. (Prior to zod@1.6.2 the validation function had to return a boolean.)
1248
- 2. The second argument accepts some options. You can use this to customize certain error-handling behavior:
1249
-
1250
- ```ts
1251
- type RefineParams = {
1252
- // override error message
1253
- message?: string;
1254
-
1255
- // appended to error path
1256
- path?: (string | number)[];
1257
-
1258
- // params object you can use to customize message
1259
- // in error map
1260
- params?: object;
1261
- };
1262
- ```
1263
-
1264
- For advanced cases, the second argument can also be a function that returns `RefineParams`/
1265
-
1266
- ```ts
1267
- z.string().refine(
1268
- (val) => val.length > 10,
1269
- (val) => ({ message: `${val} is not more than 10 characters` })
1270
- );
1271
- ```
1272
-
1273
- #### Customize error path
1274
-
1275
- ```ts
1276
- const passwordForm = z
1277
- .object({
1278
- password: z.string(),
1279
- confirm: z.string(),
1280
- })
1281
- .refine((data) => data.password === data.confirm, {
1282
- message: "Passwords don't match",
1283
- path: ["confirm"], // path of error
1284
- })
1285
- .parse({ password: "asdf", confirm: "qwer" });
1286
- ```
1287
-
1288
- Because you provided a `path` parameter, the resulting error will be:
1289
-
1290
- ```ts
1291
- ZodError {
1292
- issues: [{
1293
- "code": "custom",
1294
- "path": [ "confirm" ],
1295
- "message": "Passwords don't match"
1296
- }]
1297
- }
1298
- ```
1299
-
1300
- #### Asynchronous refinements
1301
-
1302
- Refinements can also be async:
1303
-
1304
- ```ts
1305
- const userId = z.string().refine(async (id) => {
1306
- // verify that ID exists in database
1307
- return true;
1308
- });
1309
- ```
1310
-
1311
- > โš ๏ธIf you use async refinements, you must use the `.parseAsync` method to parse data! Otherwise Zod will throw an error.
1312
-
1313
- #### Relationship to transforms
1314
-
1315
- Transforms and refinements can be interleaved:
1316
-
1317
- ```ts
1318
- z.string()
1319
- .transform((val) => val.length)
1320
- .refine((val) => val > 25);
1321
- ```
1322
-
1323
- <!-- Note that the `path` is set to `["confirm"]` , so you can easily display this error underneath the "Confirm password" textbox.
1324
-
1325
-
1326
- ```ts
1327
- const allForms = z.object({ passwordForm }).parse({
1328
- passwordForm: {
1329
- password: "asdf",
1330
- confirm: "qwer",
1331
- },
1332
- });
1333
- ```
1334
-
1335
- would result in
1336
-
1337
- ```
1338
-
1339
- ZodError {
1340
- issues: [{
1341
- "code": "custom",
1342
- "path": [ "passwordForm", "confirm" ],
1343
- "message": "Passwords don't match"
1344
- }]
1345
- }
1346
- ``` -->
1347
-
1348
- ### `.superRefine`
1349
-
1350
- The `.refine` method is actually syntactic sugar atop a more versatile (and verbose) method called `superRefine`. Here's an example:
1351
-
1352
- ```ts
1353
- const Strings = z.array(z.string()).superRefine((val, ctx) => {
1354
- if (val.length > 3) {
1355
- ctx.addIssue({
1356
- code: z.ZodIssueCode.too_big,
1357
- maximum: 3,
1358
- type: "array",
1359
- inclusive: true,
1360
- message: "Too many items ๐Ÿ˜ก",
1361
- });
1362
- }
1363
-
1364
- if (val.length !== new Set(val).size) {
1365
- ctx.addIssue({
1366
- code: z.ZodIssueCode.custom,
1367
- message: `No duplicated allowed.`,
1368
- });
1369
- }
1370
- });
1371
- ```
1372
-
1373
- You can add as many issues as you like. If `ctx.addIssue` is NOT called during the execution of the function, validation passes.
1374
-
1375
- Normally refinements always create issues with a `ZodIssueCode.custom` error code, but with `superRefine` you can create any issue of any code. Each issue code is described in detail in the Error Handling guide (ERROR_HANDLING.md).
1376
-
1377
- ### `.transform`
1378
-
1379
- To transform data after parsing, use the `transform` method.
1380
-
1381
- ```ts
1382
- const stringToNumber = z.string().transform((val) => myString.length);
1383
- stringToNumber.parse("string"); // => 6
1384
- ```
1385
-
1386
- > โš ๏ธ Transformation functions must not throw. Make sure to use refinements before the transformer to make sure the input can be parsed by the transformer.
1387
-
1388
- #### Chaining order
1389
-
1390
- 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 transformations.
1391
-
1392
- ```ts
1393
- const emailToDomain = z
1394
- .string()
1395
- .email()
1396
- .transform((val) => val.split("@")[1]);
1397
-
1398
- emailToDomain.parse("colinhacks@example.com"); // => example.com
1399
- ```
1400
-
1401
- #### Relationship to refinements
1402
-
1403
- Transforms and refinements can be interleaved:
1404
-
1405
- ```ts
1406
- z.string()
1407
- .transform((val) => val.length)
1408
- .refine((val) => val > 25);
1409
- ```
1410
-
1411
- #### Async transformations
1412
-
1413
- Transformations can also be async.
1414
-
1415
- ```ts
1416
- const IdToUser = z.transformer(
1417
- z.string().uuid(),
1418
- UserSchema,
1419
- (userId) => async (id) => {
1420
- return await getUserById(id);
1421
- }
1422
- );
1423
- ```
1424
-
1425
- > โš ๏ธ If your schema contains asynchronous transformers, you must use .parseAsync() or .safeParseAsync() to parse data. Otherwise Zod will throw an error.
1426
-
1427
- ### `.default`
1428
-
1429
- You can use transformers to implement the concept of "default values" in Zod.
1430
-
1431
- ```ts
1432
- const stringWithDefault = z.string().default("tuna");
1433
-
1434
- stringWithDefault.parse(undefined); // => "tuna"
1435
- ```
1436
-
1437
- Optionally, you can pass a function into `.default` that will be re-executed whenever a default value needs to be generated:
1438
-
1439
- ```ts
1440
- const numberWithRandomDefault = z.number().default(Math.random);
1441
-
1442
- numberWithRandomDefault.parse(undefined); // => 0.4413456736055323
1443
- numberWithRandomDefault.parse(undefined); // => 0.1871840107401901
1444
- numberWithRandomDefault.parse(undefined); // => 0.7223408162401552
1445
- ```
1446
-
1447
- ### `.optional`
1448
-
1449
- A convenience method that returns an optional version of a schema.
1450
-
1451
- ```ts
1452
- const optionalString = z.string().optional(); // string | undefined
1453
-
1454
- // equivalent to
1455
- z.optional(z.string());
1456
- ```
1457
-
1458
- ### `.nullable`
1459
-
1460
- A convenience method that returns an nullable version of a schema.
1461
-
1462
- ```ts
1463
- const nullableString = z.string().nullable(); // string | null
1464
-
1465
- // equivalent to
1466
- z.nullable(z.string());
1467
- ```
1468
-
1469
- ### `.nullish`
1470
-
1471
- 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" [here](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing).
1472
-
1473
- ```ts
1474
- const nullishString = z.string().nullish(); // string | null | undefined
1475
-
1476
- // equivalent to
1477
- z.string().optional().nullable();
1478
- ```
1479
-
1480
- ### `.array`
1481
-
1482
- A convenience method that returns an array schema for the given type:
1483
-
1484
- ```ts
1485
- const nullableString = z.string().array(); // string[]
1486
-
1487
- // equivalent to
1488
- z.array(z.string());
1489
- ```
1490
-
1491
- ### `.or`
1492
-
1493
- A convenience method for union types.
1494
-
1495
- ```ts
1496
- z.string().or(z.number()); // string | number
1497
-
1498
- // equivalent to
1499
- z.union([z.string(), z.number()]);
1500
- ```
1501
-
1502
- ### `.and`
1503
-
1504
- A convenience method for creating interesection types.
1505
-
1506
- ```ts
1507
- z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: string } & { age: number }
1508
-
1509
- // equivalent to
1510
- z.intersection(z.string(), z.number());
1511
- ```
1512
-
1513
- # Type inference
1514
-
1515
- You can extract the TypeScript type of any schema with `z.infer<typeof mySchema>` .
1516
-
1517
- ```ts
1518
- const A = z.string();
1519
- type A = z.infer<typeof A>; // string
1520
-
1521
- const u: A = 12; // TypeError
1522
- const u: A = "asdf"; // compiles
1523
- ```
1524
-
1525
- #### What about transforms?
1526
-
1527
- In reality each Zod schema is actually associated with **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`.
1528
-
1529
- You can separately extract the input and output types like so:
1530
-
1531
- ```ts
1532
- const stringToNumber = z.string().transform((val) => val.length);
1533
-
1534
- // โš ๏ธ Important: z.infer returns the OUTPUT type!
1535
- type input = z.input<stringToNumber>; // string
1536
- type output = z.output<stringToNumber>; // number
1537
-
1538
- // equivalent to z.output!
1539
- type inferred = z.infer<stringToNumber>; // number
1540
- ```
1541
-
1542
- # Errors
1543
-
1544
- Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.
1545
-
1546
- ```ts
1547
- const data = z
1548
- .object({
1549
- name: z.string(),
1550
- })
1551
- .safeParse({ name: 12 });
1552
-
1553
- if (!data.success) {
1554
- data.error.issues;
1555
- /* [
1556
- {
1557
- "code": "invalid_type",
1558
- "expected": "string",
1559
- "received": "number",
1560
- "path": [ "name" ],
1561
- "message": "Expected string, received number"
1562
- }
1563
- ] */
1564
- }
1565
- ```
1566
-
1567
- #### Error formatting
1568
-
1569
- You can use the `.format()` method to convert this error into a nested object.
1570
-
1571
- ```ts
1572
- data.error.format();
1573
- /* {
1574
- name: { _errors: [ 'Expected string, received number' ] }
1575
- } */
1576
- ```
1577
-
1578
- 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)
1579
-
1580
- # Comparison
1581
-
1582
- 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.
1583
-
1584
- <!-- The table below summarizes the feature differences. Below the table there are more involved discussions of certain alternatives, where necessary. -->
1585
-
1586
- <!-- | Feature | [Zod](https://github.com/colinhacks) | [Joi](https://github.com/hapijs/joi) | [Yup](https://github.com/jquense/yup) | [io-ts](https://github.com/gcanti/io-ts) | [Runtypes](https://github.com/pelotom/runtypes) | [ow](https://github.com/sindresorhus/ow) | [class-validator](https://github.com/typestack/class-validator) |
1587
- | ---------------------------------------------------------------------------------------------------------------------- | :-----------------------------: | :----------------------------------: | :-----------------------------------: | :--------------------------------------: | :---------------------------------------------: | :--------------------------------------: | :-------------------------------------------------------------: |
1588
- | <abbr title='Any ability to extract a TypeScript type from a validator instance counts.'>Type inference</abbr> | ๐ŸŸข | ๐Ÿ”ด | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข |
1589
- | <abbr title="Yup's inferred types are incorrect in certain cases, see discussion below.">Correct type inference</abbr> | ๐ŸŸข | ๐Ÿ”ด | ๐Ÿ”ด | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข |
1590
-
1591
- <abbr title="number, string, boolean, null, undefined">Primitive Types</abbr>
1592
- <abbr title="Includes any checks beyond 'Is this a string?', e.g. min/max length, isEmail, isURL, case checking, etc.">String Validation</abbr>
1593
- <abbr title="Includes any checks beyond 'Is this a number?', e.g. min/max, isPositive, integer vs float, etc.">Number Validation</abbr>
1594
- Dates
1595
-
1596
- Primitive Literals
1597
- Object Literals
1598
- Tuple Literals
1599
- Objects
1600
- Arrays
1601
- Non-empty arrays
1602
- Unions
1603
- Optionals
1604
- Nullable
1605
- Enums
1606
- Enum Autocomplete
1607
- Intersections
1608
- Object Merging
1609
- Tuples
1610
- Recursive Types
1611
- Function Schemas
1612
-
1613
- <abbr title="For instance, Yup allows custmo error messages with the syntax yup.number().min(5, 'Number must be more than 5!')">Validation Messages</abbr>
1614
- Immutable instances
1615
- Type Guards
1616
- Validity Checking
1617
- Casting
1618
- Default Values
1619
- Rich Errors
1620
- Branded -->
1621
-
1622
- <!-- - Missing object methods: (pick, omit, partial, deepPartial, merge, extend)
1623
-
1624
- * Missing nonempty arrays with proper typing (`[T, ...T[]]`)
1625
- * Missing lazy/recursive types
1626
- * Missing promise schemas
1627
- * Missing function schemas
1628
- * Missing union & intersection schemas
1629
- * Missing support for parsing cyclical data (maybe)
1630
- * Missing error customization -->
1631
-
1632
- #### Joi
1633
-
1634
- [https://github.com/hapijs/joi](https://github.com/hapijs/joi)
1635
-
1636
- Doesn't support static type inference ๐Ÿ˜•
1637
-
1638
- #### Yup
1639
-
1640
- [https://github.com/jquense/yup](https://github.com/jquense/yup)
1641
-
1642
- Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.
1643
-
1644
- Differences
1645
-
1646
- - Supports for casting and transformation
1647
- - All object fields are optional by default
1648
- - Missing object methods: (partial, deepPartial)
1649
- <!-- - Missing nonempty arrays with proper typing (`[T, ...T[]]`) -->
1650
- - Missing promise schemas
1651
- - Missing function schemas
1652
- - Missing union & intersection schemas
1653
-
1654
- <!-- ยน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. -->
1655
-
1656
- #### io-ts
1657
-
1658
- [https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)
1659
-
1660
- io-ts is an excellent library by gcanti. The API of io-ts heavily inspired the design of Zod.
1661
-
1662
- In our experience, io-ts prioritizes functional programming purity over developer experience in many cases. This is a valid and admirable design goal, but it makes io-ts particularly hard to integrate into an existing codebase with a more procedural or object-oriented bias. For instance, consider how to define an object with optional properties in io-ts:
1663
-
1664
- ```ts
1665
- import * as t from "io-ts";
1666
-
1667
- const A = t.type({
1668
- foo: t.string,
1669
- });
1670
-
1671
- const B = t.partial({
1672
- bar: t.number,
1673
- });
1674
-
1675
- const C = t.intersection([A, B]);
1676
-
1677
- type C = t.TypeOf<typeof C>;
1678
- // returns { foo: string; bar?: number | undefined }
1679
- ```
1680
-
1681
- You must define the required and optional props in separate object validators, pass the optionals through `t.partial` (which marks all properties as optional), then combine them with `t.intersection` .
1682
-
1683
- Consider the equivalent in Zod:
1684
-
1685
- ```ts
1686
- const C = z.object({
1687
- foo: z.string(),
1688
- bar: z.number().optional(),
1689
- });
1690
-
1691
- type C = z.infer<typeof C>;
1692
- // returns { foo: string; bar?: number | undefined }
1693
- ```
1694
-
1695
- This more declarative API makes schema definitions vastly more concise.
1696
-
1697
- `io-ts` also requires the use of gcanti's functional programming library `fp-ts` to parse results and handle errors. This is another fantastic resource for developers looking to keep their codebase strictly functional. But depending on `fp-ts` necessarily comes with a lot of intellectual overhead; a developer has to be familiar with functional programming concepts and the `fp-ts` nomenclature to use the library.
1698
-
1699
- - Supports codecs with serialization & deserialization transforms
1700
- - Supports branded types
1701
- - Supports advanced functional programming, higher-kinded types, `fp-ts` compatibility
1702
- - Missing object methods: (pick, omit, partial, deepPartial, merge, extend)
1703
- - Missing nonempty arrays with proper typing (`[T, ...T[]]`)
1704
- - Missing promise schemas
1705
- - Missing function schemas
1706
-
1707
- #### Runtypes
1708
-
1709
- [https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
1710
-
1711
- Good type inference support, but limited options for object type masking (no `.pick` , `.omit` , `.extend` , etc.). No support for `Record` s (their `Record` is equivalent to Zod's `object` ). They DO support branded and readonly types, which Zod does not.
1712
-
1713
- - Supports "pattern matching": computed properties that distribute over unions
1714
- - Supports readonly types
1715
- - Missing object methods: (deepPartial, merge)
1716
- - Missing nonempty arrays with proper typing (`[T, ...T[]]`)
1717
- - Missing promise schemas
1718
- - Missing error customization
1719
-
1720
- #### Ow
1721
-
1722
- [https://github.com/sindresorhus/ow](https://github.com/sindresorhus/ow)
1723
-
1724
- Ow is focused on function input validation. It's a library that makes it easy to express complicated assert statements, but it doesn't let you parse untyped data. They support a much wider variety of types; Zod has a nearly one-to-one mapping with TypeScript's type system, whereas ow lets you validate several highly-specific types out of the box (e.g. `int32Array` , see full list in their README).
1725
-
1726
- 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.
1727
-
1728
- # Changelog
1729
-
1730
- View the changelog at [CHANGELOG.md](CHANGELOG.md)