zod 3.19.1 → 3.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +316 -76
- package/lib/ZodError.d.ts +15 -9
- package/lib/ZodError.js +1 -0
- package/lib/external.d.ts +1 -1
- package/lib/external.js +1 -4
- package/lib/helpers/errorUtil.d.ts +2 -6
- package/lib/helpers/parseUtil.js +3 -3
- package/lib/helpers/typeAliases.d.ts +1 -1
- package/lib/helpers/util.js +2 -0
- package/lib/index.mjs +454 -53
- package/lib/index.umd.js +489 -82
- package/lib/locales/en.js +27 -8
- package/lib/types.d.ts +261 -67
- package/lib/types.js +509 -127
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -83,13 +83,15 @@
|
|
|
83
83
|
- [Records](#records)
|
|
84
84
|
- [Maps](#maps)
|
|
85
85
|
- [Sets](#sets)
|
|
86
|
+
- [Intersections](#intersections)
|
|
86
87
|
- [Recursive types](#recursive-types)
|
|
87
88
|
- [JSON type](#json-type)
|
|
88
89
|
- [Cyclical data](#cyclical-objects)
|
|
89
90
|
- [Promises](#promises)
|
|
90
91
|
- [Instanceof](#instanceof)
|
|
91
|
-
- [
|
|
92
|
+
- [Functions](#function-schemas)
|
|
92
93
|
- [Preprocess](#preprocess)
|
|
94
|
+
- [Custom](#custom)
|
|
93
95
|
- [Schema methods](#schema-methods)
|
|
94
96
|
- [.parse](#parse)
|
|
95
97
|
- [.parseAsync](#parseasync)
|
|
@@ -99,6 +101,7 @@
|
|
|
99
101
|
- [.superRefine](#superRefine)
|
|
100
102
|
- [.transform](#transform)
|
|
101
103
|
- [.default](#default)
|
|
104
|
+
- [.catch](#catch)
|
|
102
105
|
- [.optional](#optional)
|
|
103
106
|
- [.nullable](#nullable)
|
|
104
107
|
- [.nullish](#nullish)
|
|
@@ -132,7 +135,7 @@ Some other great aspects:
|
|
|
132
135
|
- Zero dependencies
|
|
133
136
|
- Works in Node.js and all modern browsers
|
|
134
137
|
- Tiny: 8kb minified + zipped
|
|
135
|
-
- Immutable: methods (
|
|
138
|
+
- Immutable: methods (e.g. `.optional()`) return a new instance
|
|
136
139
|
- Concise, chainable interface
|
|
137
140
|
- Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
|
|
138
141
|
- Works with plain JavaScript too! You don't need to use TypeScript.
|
|
@@ -177,13 +180,22 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
177
180
|
<tr>
|
|
178
181
|
<td align="center">
|
|
179
182
|
<a href="https://deletype.com/">
|
|
180
|
-
<img src="https://avatars0.githubusercontent.com/u/15068039?s=200&v=4" width="200px;" alt="" />
|
|
183
|
+
<img src="https://avatars0.githubusercontent.com/u/15068039?s=200&v=4" width="200px;" alt="Deletype logo" />
|
|
181
184
|
</a>
|
|
182
185
|
<br />
|
|
183
186
|
<b>Deletype</b>
|
|
184
187
|
<br />
|
|
185
188
|
<a href="https://deletype.com">deletype.com</a>
|
|
186
189
|
</td>
|
|
190
|
+
<td align="center">
|
|
191
|
+
<a href="https://proxy.com/">
|
|
192
|
+
<img src="https://avatars.githubusercontent.com/u/14321439?s=200&v=4" width="200px;" alt="Proxy logo" />
|
|
193
|
+
</a>
|
|
194
|
+
<br />
|
|
195
|
+
<b>Proxy</b>
|
|
196
|
+
<br />
|
|
197
|
+
<a href="https://proxy.com">proxy.com</a>
|
|
198
|
+
</td>
|
|
187
199
|
</tr>
|
|
188
200
|
</table>
|
|
189
201
|
|
|
@@ -191,16 +203,27 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
191
203
|
|
|
192
204
|
<table>
|
|
193
205
|
<tr>
|
|
206
|
+
<td align="center" colspan="2">
|
|
207
|
+
<a href="https://www.numeric.io">
|
|
208
|
+
<img src="https://i.imgur.com/kTiLtZt.png" width="250px;" alt="Numeric logo" />
|
|
209
|
+
</a>
|
|
210
|
+
<br />
|
|
211
|
+
<b>Numeric</b>
|
|
212
|
+
<br />
|
|
213
|
+
<a href="https://www.numeric.io">numeric.io</a>
|
|
214
|
+
</td>
|
|
194
215
|
<td align="center">
|
|
195
216
|
<a href="https://snaplet.dev">
|
|
196
|
-
<img src="https://avatars.githubusercontent.com/u/69029941?s=200&v=4" width="150px;" alt="" />
|
|
217
|
+
<img src="https://avatars.githubusercontent.com/u/69029941?s=200&v=4" width="150px;" alt="Snaplet logo" />
|
|
197
218
|
</a>
|
|
198
219
|
<br />
|
|
199
220
|
<b>Snaplet</b>
|
|
200
221
|
<br />
|
|
201
222
|
<a href="https://snaplet.dev">snaplet.dev</a>
|
|
202
223
|
</td>
|
|
203
|
-
|
|
224
|
+
</tr>
|
|
225
|
+
<tr>
|
|
226
|
+
<td align="center">
|
|
204
227
|
<a href="https://marcatopartners.com/">
|
|
205
228
|
<img src="https://avatars.githubusercontent.com/u/84106192?s=200&v=4" width="150px;" alt="Marcato Partners" />
|
|
206
229
|
</a>
|
|
@@ -210,14 +233,14 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
210
233
|
<a href="https://marcatopartners.com/">marcatopartners.com</a>
|
|
211
234
|
</td>
|
|
212
235
|
<td align="center">
|
|
213
|
-
<a href="https://
|
|
214
|
-
<img src="https://avatars.githubusercontent.com/u/
|
|
236
|
+
<a href="https://interval.com">
|
|
237
|
+
<img src="https://avatars.githubusercontent.com/u/67802063?s=200&v=4" width="150px;" alt="" />
|
|
215
238
|
</a>
|
|
216
239
|
<br />
|
|
217
|
-
<b>
|
|
240
|
+
<b>Interval</b>
|
|
241
|
+
<br />
|
|
242
|
+
<a href="https://interval.com">interval.com</a>
|
|
218
243
|
</td>
|
|
219
|
-
</tr>
|
|
220
|
-
<tr>
|
|
221
244
|
<td align="center">
|
|
222
245
|
<a href="https://seasoned.cc">
|
|
223
246
|
<img src="https://avatars.githubusercontent.com/u/33913103?s=200&v=4" width="150px;" alt="" />
|
|
@@ -227,14 +250,16 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
227
250
|
<br />
|
|
228
251
|
<a href="https://seasoned.cc">seasoned.cc</a>
|
|
229
252
|
</td>
|
|
253
|
+
</tr>
|
|
254
|
+
<tr>
|
|
230
255
|
<td align="center">
|
|
231
|
-
<a href="https://
|
|
232
|
-
<img src="https://avatars.githubusercontent.com/u/
|
|
256
|
+
<a href="https://www.bamboocreative.nz/">
|
|
257
|
+
<img src="https://avatars.githubusercontent.com/u/41406870?v=4" width="150px;" alt="Bamboo Creative logo" />
|
|
233
258
|
</a>
|
|
234
259
|
<br />
|
|
235
|
-
<b>
|
|
260
|
+
<b>Bamboo Creative</b>
|
|
236
261
|
<br />
|
|
237
|
-
<a href="https://
|
|
262
|
+
<a href="https://www.bamboocreative.nz">bamboocreative.nz</a>
|
|
238
263
|
</td>
|
|
239
264
|
</tr>
|
|
240
265
|
</table>
|
|
@@ -275,6 +300,16 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
275
300
|
</td>
|
|
276
301
|
</tr>
|
|
277
302
|
<tr>
|
|
303
|
+
<td align="center">
|
|
304
|
+
<a href="https://fungible.systems/">
|
|
305
|
+
<img src="https://avatars.githubusercontent.com/u/80220121?s=200&v=4" width="100px;" alt="Fungible Systems logo"/>
|
|
306
|
+
</a>
|
|
307
|
+
<br />
|
|
308
|
+
<b>Fungible Systems</b>
|
|
309
|
+
<br/>
|
|
310
|
+
<a href="https://fungible.systems/">fungible.systems</a>
|
|
311
|
+
<br />
|
|
312
|
+
</td>
|
|
278
313
|
<td align="center">
|
|
279
314
|
<a href="https://adaptable.io/">
|
|
280
315
|
<img src="https://avatars.githubusercontent.com/u/60378268?s=200&v=4" width="100px;" alt=""/>
|
|
@@ -303,46 +338,70 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
303
338
|
|
|
304
339
|
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.
|
|
305
340
|
|
|
341
|
+
#### Resources
|
|
342
|
+
|
|
343
|
+
- [Total TypeScript Zod Tutorial](https://www.totaltypescript.com/tutorials/zod) by [@mattpocockuk](https://twitter.com/mattpocockuk)
|
|
344
|
+
- [Fixing TypeScript's Blindspot: Runtime Typechecking](https://www.youtube.com/watch?v=rY_XqfSHock) by [@jherr](https://twitter.com/jherr)
|
|
345
|
+
|
|
346
|
+
#### API libraries
|
|
347
|
+
|
|
306
348
|
- [`tRPC`](https://github.com/trpc/trpc): Build end-to-end typesafe APIs without GraphQL.
|
|
307
|
-
- [`ts-to-zod`](https://github.com/fabien0102/ts-to-zod): Convert TypeScript definitions into Zod schemas.
|
|
308
|
-
- [`zod-to-ts`](https://github.com/sachinraja/zod-to-ts): Generate TypeScript definitions from Zod schemas.
|
|
309
|
-
- [`@anatine/zod-openapi`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi): Converts a Zod schema to an OpenAPI v3.x `SchemaObject`.
|
|
310
|
-
- [`@anatine/zod-mock`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock): Generate mock data from a Zod schema. Powered by [faker.js](https://github.com/Marak/Faker.js).
|
|
311
349
|
- [`@anatine/zod-nestjs`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-nestjs): Helper methods for using Zod in a NestJS project.
|
|
312
|
-
- [`zod-mocking`](https://github.com/dipasqualew/zod-mocking): Generate mock data from your Zod schemas.
|
|
313
|
-
- [`zod-fast-check`](https://github.com/DavidTimms/zod-fast-check): Generate `fast-check` arbitraries from Zod schemas.
|
|
314
350
|
- [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
|
|
351
|
+
- [`domain-functions`](https://github.com/SeasonedSoftware/domain-functions/): Decouple your business logic from your framework using composable functions. With first-class type inference from end to end powered by Zod schemas.
|
|
352
|
+
- [`@zodios/core`](https://github.com/ecyrbe/zodios): A typescript API client with runtime and compile time validation backed by axios and zod.
|
|
315
353
|
- [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares.
|
|
354
|
+
|
|
355
|
+
#### Form integrations
|
|
356
|
+
|
|
357
|
+
- [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form.
|
|
358
|
+
- [`zod-validation-error`](https://github.com/causaly/zod-validation-error): Generate user-friendly error messages from `ZodError`s
|
|
359
|
+
- [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod.
|
|
360
|
+
- [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod.
|
|
361
|
+
- [`zodix`](https://github.com/rileytomasek/zodix): Zod utilities for FormData and URLSearchParams in Remix loaders and actions.
|
|
362
|
+
- [`formik-validator-zod`](https://github.com/glazy/formik-validator-zod): Formik-compliant validator library that simplifies using Zod with Formik.
|
|
363
|
+
- [`zod-i18n-map`](https://github.com/aiji42/zod-i18n): Useful for translating Zod error messages.
|
|
364
|
+
|
|
365
|
+
#### Zod to X
|
|
366
|
+
|
|
367
|
+
- [`zod-to-ts`](https://github.com/sachinraja/zod-to-ts): Generate TypeScript definitions from Zod schemas.
|
|
316
368
|
- [`zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema): Convert your Zod schemas into [JSON Schemas](https://json-schema.org/).
|
|
369
|
+
- [`@anatine/zod-openapi`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi): Converts a Zod schema to an OpenAPI v3.x `SchemaObject`.
|
|
370
|
+
- [`zod-fast-check`](https://github.com/DavidTimms/zod-fast-check): Generate `fast-check` arbitraries from Zod schemas.
|
|
371
|
+
- [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema.
|
|
372
|
+
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas.
|
|
373
|
+
- [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters.
|
|
374
|
+
- [`nestjs-graphql-zod`](https://github.com/incetarik/nestjs-graphql-zod): Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.
|
|
375
|
+
|
|
376
|
+
#### X to Zod
|
|
377
|
+
|
|
378
|
+
- [`ts-to-zod`](https://github.com/fabien0102/ts-to-zod): Convert TypeScript definitions into Zod schemas.
|
|
379
|
+
- [`@runtyping/zod`](https://github.com/johngeorgewright/runtyping/tree/master/packages/zod): Generate Zod from static types & JSON schema.
|
|
317
380
|
- [`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/).
|
|
318
381
|
- [`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/).
|
|
319
|
-
- [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema.
|
|
320
|
-
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
321
382
|
- [`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
|
|
322
383
|
- [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema.
|
|
323
|
-
- [`
|
|
324
|
-
- [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs
|
|
325
|
-
- [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters
|
|
384
|
+
- [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs.
|
|
326
385
|
- [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
|
|
327
386
|
- [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
|
|
328
|
-
- [`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.
|
|
329
|
-
- [`zod-xlsx`](https://github.com/sidwebworks/zod-xlsx): A xlsx based resource validator using Zod schemas.
|
|
330
|
-
- [`remix-domains`](https://github.com/SeasonedSoftware/remix-domains/): Improves end-to-end type safety in [Remix](https://remix.run/) by leveraging Zod to parse the framework's inputs such as FormData, URLSearchParams, etc.
|
|
331
|
-
- [`@zodios/core`](https://github.com/ecyrbe/zodios): A typescript API client with runtime and compile time validation backed by axios and zod.
|
|
332
|
-
- [`@runtyping/zod`](https://github.com/johngeorgewright/runtyping/tree/master/packages/zod): Generate zod from static types & JSON schema.
|
|
333
|
-
- [`slonik`](https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference): Node.js Postgres client with strong Zod integration
|
|
334
387
|
|
|
335
|
-
####
|
|
388
|
+
#### Mocking
|
|
389
|
+
|
|
390
|
+
- [`@anatine/zod-mock`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock): Generate mock data from a Zod schema. Powered by [faker.js](https://github.com/Marak/Faker.js).
|
|
391
|
+
- [`zod-mocking`](https://github.com/dipasqualew/zod-mocking): Generate mock data from your Zod schemas.
|
|
336
392
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
- [`
|
|
393
|
+
#### Powered by Zod
|
|
394
|
+
|
|
395
|
+
- [`slonik`](https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference): Node.js Postgres client with strong Zod integration.
|
|
396
|
+
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
397
|
+
- [`zod-xlsx`](https://github.com/sidwebworks/zod-xlsx): A xlsx based resource validator using Zod schemas.
|
|
398
|
+
- [`znv`](https://github.com/lostfictions/znv): Type-safe environment parsing and validation for Node.js with Zod schemas
|
|
340
399
|
|
|
341
400
|
## Installation
|
|
342
401
|
|
|
343
402
|
### Requirements
|
|
344
403
|
|
|
345
|
-
- TypeScript 4.
|
|
404
|
+
- TypeScript 4.5+!
|
|
346
405
|
- You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects.
|
|
347
406
|
|
|
348
407
|
```ts
|
|
@@ -356,17 +415,16 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
356
415
|
}
|
|
357
416
|
```
|
|
358
417
|
|
|
359
|
-
### Node/
|
|
360
|
-
|
|
361
|
-
To install Zod v3:
|
|
418
|
+
### From `npm` (Node/Bun)
|
|
362
419
|
|
|
363
420
|
```sh
|
|
364
421
|
npm install zod # npm
|
|
365
422
|
yarn add zod # yarn
|
|
423
|
+
bun add zod # bun
|
|
366
424
|
pnpm add zod # pnpm
|
|
367
425
|
```
|
|
368
426
|
|
|
369
|
-
### Deno
|
|
427
|
+
### From `deno.land/x` (Deno)
|
|
370
428
|
|
|
371
429
|
Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on [deno.land/x](https://deno.land/x). The latest version can be imported like so:
|
|
372
430
|
|
|
@@ -428,6 +486,7 @@ z.number();
|
|
|
428
486
|
z.bigint();
|
|
429
487
|
z.boolean();
|
|
430
488
|
z.date();
|
|
489
|
+
z.symbol();
|
|
431
490
|
|
|
432
491
|
// empty types
|
|
433
492
|
z.undefined();
|
|
@@ -449,8 +508,12 @@ z.never();
|
|
|
449
508
|
```ts
|
|
450
509
|
const tuna = z.literal("tuna");
|
|
451
510
|
const twelve = z.literal(12);
|
|
511
|
+
const twobig = z.literal(2n); // bigint literal
|
|
452
512
|
const tru = z.literal(true);
|
|
453
513
|
|
|
514
|
+
const terrificSymbol = Symbol("terrific");
|
|
515
|
+
const terrific = z.literal(terrificSymbol);
|
|
516
|
+
|
|
454
517
|
// retrieve literal value
|
|
455
518
|
tuna.value; // "tuna"
|
|
456
519
|
```
|
|
@@ -472,18 +535,11 @@ z.string().cuid();
|
|
|
472
535
|
z.string().regex(regex);
|
|
473
536
|
z.string().startsWith(string);
|
|
474
537
|
z.string().endsWith(string);
|
|
475
|
-
|
|
476
|
-
//
|
|
477
|
-
z.string().trim();
|
|
478
|
-
|
|
479
|
-
// deprecated, equivalent to .min(1)
|
|
480
|
-
z.string().nonempty();
|
|
481
|
-
|
|
482
|
-
// optional custom error message
|
|
483
|
-
z.string().nonempty({ message: "Can't be empty" });
|
|
538
|
+
z.string().trim(); // trim whitespace
|
|
539
|
+
z.string().datetime(); // defaults to UTC, see below for options
|
|
484
540
|
```
|
|
485
541
|
|
|
486
|
-
> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
|
|
542
|
+
> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions that can be used in conjunction with [Refinements](#refine).
|
|
487
543
|
|
|
488
544
|
You can customize some common error messages when creating a string schema.
|
|
489
545
|
|
|
@@ -505,6 +561,67 @@ z.string().url({ message: "Invalid url" });
|
|
|
505
561
|
z.string().uuid({ message: "Invalid UUID" });
|
|
506
562
|
z.string().startsWith("https://", { message: "Must provide secure URL" });
|
|
507
563
|
z.string().endsWith(".com", { message: "Only .com domains allowed" });
|
|
564
|
+
z.string().datetime({ message: "Invalid datetime string! Must be UTC." });
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
## Coercion for primitives
|
|
568
|
+
|
|
569
|
+
Zod now provides a more convenient way to coerce primitive values.
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
const schema = z.coerce.string();
|
|
573
|
+
schema.parse("tuna"); // => "tuna"
|
|
574
|
+
schema.parse(12); // => "12"
|
|
575
|
+
schema.parse(true); // => "true"
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
During the parsing step, the input is passed through the `String()` function, which is a JavaScript built-in for coercing data into strings. Note that the returned schema is a `ZodString` instance so you can use all string methods.
|
|
579
|
+
|
|
580
|
+
```ts
|
|
581
|
+
z.coerce.string().email().min(5);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
All primitive types support coercion.
|
|
585
|
+
|
|
586
|
+
```ts
|
|
587
|
+
z.coerce.string(); // String(input)
|
|
588
|
+
z.coerce.number(); // Number(input)
|
|
589
|
+
z.coerce.boolean(); // Boolean(input)
|
|
590
|
+
z.coerce.bigint(); // BigInt(input)
|
|
591
|
+
z.coerce.date(); // new Date(input)
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Datetime validation
|
|
595
|
+
|
|
596
|
+
The `z.string().datetime()` method defaults to UTC validation: no timezone offsets with arbitrary sub-second decimal precision.
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
const datetime = z.string().datetime();
|
|
600
|
+
|
|
601
|
+
datetime.parse("2020-01-01T00:00:00Z"); // pass
|
|
602
|
+
datetime.parse("2020-01-01T00:00:00.123Z"); // pass
|
|
603
|
+
datetime.parse("2020-01-01T00:00:00.123456Z"); // pass (arbitrary precision)
|
|
604
|
+
datetime.parse("2020-01-01T00:00:00+02:00"); // fail (no offsets allowed)
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
Timezone offsets can be allowed by setting the `offset` option to `true`.
|
|
608
|
+
|
|
609
|
+
```ts
|
|
610
|
+
const datetime = z.string().datetime({ offset: true });
|
|
611
|
+
|
|
612
|
+
datetime.parse("2020-01-01T00:00:00+02:00"); // pass
|
|
613
|
+
datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional)
|
|
614
|
+
datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported)
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
You can additionally constrain the allowable `precision`. By default, arbitrary sub-second precision is supported (but optional).
|
|
618
|
+
|
|
619
|
+
```ts
|
|
620
|
+
const datetime = z.string().datetime({ precision: 3 });
|
|
621
|
+
|
|
622
|
+
datetime.parse("2020-01-01T00:00:00.123Z"); // pass
|
|
623
|
+
datetime.parse("2020-01-01T00:00:00Z"); // fail
|
|
624
|
+
datetime.parse("2020-01-01T00:00:00.123456Z"); // fail
|
|
508
625
|
```
|
|
509
626
|
|
|
510
627
|
## Numbers
|
|
@@ -534,6 +651,8 @@ z.number().negative(); // < 0
|
|
|
534
651
|
z.number().nonpositive(); // <= 0
|
|
535
652
|
|
|
536
653
|
z.number().multipleOf(5); // Evenly divisible by 5. Alias .step(5)
|
|
654
|
+
|
|
655
|
+
z.number().finite(); // value must be finite, not Infinity or -Infinity
|
|
537
656
|
```
|
|
538
657
|
|
|
539
658
|
Optionally, you can pass in a second argument to provide a custom error message.
|
|
@@ -758,7 +877,7 @@ nullableString.parse(null); // => null
|
|
|
758
877
|
Or use the `.nullable()` method.
|
|
759
878
|
|
|
760
879
|
```ts
|
|
761
|
-
const E = z.string().nullable(); // equivalent to
|
|
880
|
+
const E = z.string().nullable(); // equivalent to nullableString
|
|
762
881
|
type E = z.infer<typeof E>; // string | null
|
|
763
882
|
```
|
|
764
883
|
|
|
@@ -927,6 +1046,41 @@ const deepPartialUser = user.deepPartial();
|
|
|
927
1046
|
|
|
928
1047
|
> Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.
|
|
929
1048
|
|
|
1049
|
+
### `.required`
|
|
1050
|
+
|
|
1051
|
+
Contrary to the `.partial` method, the `.required` method makes all properties required.
|
|
1052
|
+
|
|
1053
|
+
Starting from this object:
|
|
1054
|
+
|
|
1055
|
+
```ts
|
|
1056
|
+
const user = z.object({
|
|
1057
|
+
email: z.string()
|
|
1058
|
+
username: z.string(),
|
|
1059
|
+
}).partial();
|
|
1060
|
+
// { email?: string | undefined; username?: string | undefined }
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
We can create a required version:
|
|
1064
|
+
|
|
1065
|
+
```ts
|
|
1066
|
+
const requiredUser = user.required();
|
|
1067
|
+
// { email: string; username: string }
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
You can also specify which properties to make required:
|
|
1071
|
+
|
|
1072
|
+
```ts
|
|
1073
|
+
const requiredEmail = user.required({
|
|
1074
|
+
email: true,
|
|
1075
|
+
});
|
|
1076
|
+
/*
|
|
1077
|
+
{
|
|
1078
|
+
email: string;
|
|
1079
|
+
username?: string | undefined;
|
|
1080
|
+
}
|
|
1081
|
+
*/
|
|
1082
|
+
```
|
|
1083
|
+
|
|
930
1084
|
### `.passthrough`
|
|
931
1085
|
|
|
932
1086
|
By default Zod object schemas strip out unrecognized keys during parsing.
|
|
@@ -1103,21 +1257,25 @@ const stringOrNumber = z.string().or(z.number());
|
|
|
1103
1257
|
|
|
1104
1258
|
## Discriminated unions
|
|
1105
1259
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1260
|
+
A discriminated union is a union of object schemas that all share a particular key.
|
|
1261
|
+
|
|
1262
|
+
```ts
|
|
1263
|
+
type MyUnion =
|
|
1264
|
+
| { status: "success"; data: string }
|
|
1265
|
+
| { status: "failed"; error: Error };
|
|
1266
|
+
```
|
|
1108
1267
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing
|
|
1112
|
-
against it, and showing only the issues related to this "option".
|
|
1268
|
+
Such unions can be represented with the `z.discriminatedUnion` method. This enables faster evaluation, because Zod can check the _discriminator key_ (`status` in the example above) to determine which schema should be used to parse the input. This makes parsing more efficient and lets Zod report friendlier errors.
|
|
1269
|
+
|
|
1270
|
+
With the basic union method the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".
|
|
1113
1271
|
|
|
1114
1272
|
```ts
|
|
1115
|
-
const
|
|
1116
|
-
.
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1273
|
+
const myUnion = z.discriminatedUnion("status", [
|
|
1274
|
+
z.object({ status: z.literal("success"), data: z.string() }),
|
|
1275
|
+
z.object({ status: z.literal("failed"), error: z.instanceof(Error) }),
|
|
1276
|
+
]);
|
|
1277
|
+
|
|
1278
|
+
myUnion.parse({ type: "success", data: "yippie ki yay" });
|
|
1121
1279
|
```
|
|
1122
1280
|
|
|
1123
1281
|
## Records
|
|
@@ -1396,6 +1554,7 @@ const myFunction = z
|
|
|
1396
1554
|
.function()
|
|
1397
1555
|
.args(z.string(), z.number()) // accepts an arbitrary number of arguments
|
|
1398
1556
|
.returns(z.boolean());
|
|
1557
|
+
|
|
1399
1558
|
type myFunction = z.infer<typeof myFunction>;
|
|
1400
1559
|
// => (arg0: string, arg1: number)=>boolean
|
|
1401
1560
|
```
|
|
@@ -1437,8 +1596,9 @@ const myFunction = z
|
|
|
1437
1596
|
.function()
|
|
1438
1597
|
.args(z.string())
|
|
1439
1598
|
.implement((arg) => {
|
|
1440
|
-
return [arg.length];
|
|
1599
|
+
return [arg.length];
|
|
1441
1600
|
});
|
|
1601
|
+
|
|
1442
1602
|
myFunction; // (arg: string)=>number[]
|
|
1443
1603
|
```
|
|
1444
1604
|
|
|
@@ -1459,6 +1619,8 @@ myFunction.returnType();
|
|
|
1459
1619
|
|
|
1460
1620
|
## Preprocess
|
|
1461
1621
|
|
|
1622
|
+
> Zod now supports primitive coercion without the need for `.preprocess()`. See the [coercion docs](#coercion-for-primitives) for more information.
|
|
1623
|
+
|
|
1462
1624
|
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).)
|
|
1463
1625
|
|
|
1464
1626
|
But sometimes you want to apply some transform to the input _before_ parsing happens. A common use case: type coercion. Zod enables this with the `z.preprocess()`.
|
|
@@ -1469,6 +1631,22 @@ const castToString = z.preprocess((val) => String(val), z.string());
|
|
|
1469
1631
|
|
|
1470
1632
|
This returns a `ZodEffects` instance. `ZodEffects` is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.
|
|
1471
1633
|
|
|
1634
|
+
## Custom schemas
|
|
1635
|
+
|
|
1636
|
+
You can create a Zod schema for any TypeScript type by using `z.custom()`. This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.
|
|
1637
|
+
|
|
1638
|
+
```ts
|
|
1639
|
+
const px = z.custom<`${number}px`>((val) => /^\d+px$/.test(val));
|
|
1640
|
+
px.parse("100px"); // pass
|
|
1641
|
+
px.parse("100vw"); // fail
|
|
1642
|
+
```
|
|
1643
|
+
|
|
1644
|
+
If you don't provide a validation function, Zod will allow any value. This can be dangerous!
|
|
1645
|
+
|
|
1646
|
+
```ts
|
|
1647
|
+
z.custom<{ arg: string }>(); // performs no validation
|
|
1648
|
+
```
|
|
1649
|
+
|
|
1472
1650
|
## Schema methods
|
|
1473
1651
|
|
|
1474
1652
|
All Zod schemas contain certain methods.
|
|
@@ -1483,6 +1661,7 @@ Given any Zod schema, you can call its `.parse` method to check `data` is valid.
|
|
|
1483
1661
|
|
|
1484
1662
|
```ts
|
|
1485
1663
|
const stringSchema = z.string();
|
|
1664
|
+
|
|
1486
1665
|
stringSchema.parse("fish"); // => returns "fish"
|
|
1487
1666
|
stringSchema.parse(12); // throws Error('Non-string type: number');
|
|
1488
1667
|
```
|
|
@@ -1586,7 +1765,7 @@ type RefineParams = {
|
|
|
1586
1765
|
For advanced cases, the second argument can also be a function that returns `RefineParams`/
|
|
1587
1766
|
|
|
1588
1767
|
```ts
|
|
1589
|
-
z.string().refine(
|
|
1768
|
+
const longString = z.string().refine(
|
|
1590
1769
|
(val) => val.length > 10,
|
|
1591
1770
|
(val) => ({ message: `${val} is not more than 10 characters` })
|
|
1592
1771
|
);
|
|
@@ -1603,8 +1782,9 @@ const passwordForm = z
|
|
|
1603
1782
|
.refine((data) => data.password === data.confirm, {
|
|
1604
1783
|
message: "Passwords don't match",
|
|
1605
1784
|
path: ["confirm"], // path of error
|
|
1606
|
-
})
|
|
1607
|
-
|
|
1785
|
+
});
|
|
1786
|
+
|
|
1787
|
+
passwordForm.parse({ password: "asdf", confirm: "qwer" });
|
|
1608
1788
|
```
|
|
1609
1789
|
|
|
1610
1790
|
Because you provided a `path` parameter, the resulting error will be:
|
|
@@ -1644,7 +1824,6 @@ z.string()
|
|
|
1644
1824
|
|
|
1645
1825
|
<!-- Note that the `path` is set to `["confirm"]` , so you can easily display this error underneath the "Confirm password" textbox.
|
|
1646
1826
|
|
|
1647
|
-
|
|
1648
1827
|
```ts
|
|
1649
1828
|
const allForms = z.object({ passwordForm }).parse({
|
|
1650
1829
|
passwordForm: {
|
|
@@ -1721,12 +1900,40 @@ const schema = z.number().superRefine((val, ctx) => {
|
|
|
1721
1900
|
});
|
|
1722
1901
|
```
|
|
1723
1902
|
|
|
1903
|
+
#### Type refinements
|
|
1904
|
+
|
|
1905
|
+
If you provide a [type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) to `.refine()` or `superRefine()`, the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:
|
|
1906
|
+
|
|
1907
|
+
```ts
|
|
1908
|
+
const schema = z
|
|
1909
|
+
.object({
|
|
1910
|
+
first: z.string(),
|
|
1911
|
+
second: z.number(),
|
|
1912
|
+
})
|
|
1913
|
+
.nullable()
|
|
1914
|
+
.superRefine((arg, ctx): arg is { first: string; second: number } => {
|
|
1915
|
+
if (!arg) {
|
|
1916
|
+
ctx.addIssue({
|
|
1917
|
+
code: z.ZodIssueCode.custom, // customize your issue
|
|
1918
|
+
message: "object should exist",
|
|
1919
|
+
});
|
|
1920
|
+
return false;
|
|
1921
|
+
}
|
|
1922
|
+
return true;
|
|
1923
|
+
})
|
|
1924
|
+
// here, TS knows that arg is not null
|
|
1925
|
+
.refine((arg) => arg.first === "bob", "`first` is not `bob`!");
|
|
1926
|
+
```
|
|
1927
|
+
|
|
1928
|
+
> ⚠️ You must **still** call `ctx.addIssue()` if using `superRefine()` with a type predicate function. Otherwise the refinement won't be validated.
|
|
1929
|
+
|
|
1724
1930
|
### `.transform`
|
|
1725
1931
|
|
|
1726
1932
|
To transform data after parsing, use the `transform` method.
|
|
1727
1933
|
|
|
1728
1934
|
```ts
|
|
1729
1935
|
const stringToNumber = z.string().transform((val) => val.length);
|
|
1936
|
+
|
|
1730
1937
|
stringToNumber.parse("string"); // => 6
|
|
1731
1938
|
```
|
|
1732
1939
|
|
|
@@ -1773,7 +1980,7 @@ const Strings = z.string().transform((val, ctx) => {
|
|
|
1773
1980
|
Transforms and refinements can be interleaved. These will be executed in the order they are declared.
|
|
1774
1981
|
|
|
1775
1982
|
```ts
|
|
1776
|
-
z.string()
|
|
1983
|
+
const nameToGreeting = z.string()
|
|
1777
1984
|
.transform((val) => val.toUpperCase())
|
|
1778
1985
|
.refine((val) => val.length > 15)
|
|
1779
1986
|
.transform((val) => `Hello ${val}`)
|
|
@@ -1815,6 +2022,37 @@ numberWithRandomDefault.parse(undefined); // => 0.1871840107401901
|
|
|
1815
2022
|
numberWithRandomDefault.parse(undefined); // => 0.7223408162401552
|
|
1816
2023
|
```
|
|
1817
2024
|
|
|
2025
|
+
Conceptually, this is how Zod processes default values:
|
|
2026
|
+
|
|
2027
|
+
1. If the input is `undefined`, the default value is returned
|
|
2028
|
+
2. Otherwise, the data is parsed using the base schema
|
|
2029
|
+
|
|
2030
|
+
### `.catch`
|
|
2031
|
+
|
|
2032
|
+
Use `.catch()` to provide a "catch value" to be returned in the event of a parsing error.
|
|
2033
|
+
|
|
2034
|
+
```ts
|
|
2035
|
+
const numberWithCatch = z.number().catch(42);
|
|
2036
|
+
|
|
2037
|
+
numberWithCatch.parse(5); // => 5
|
|
2038
|
+
numberWithCatch.parse("tuna"); // => 42
|
|
2039
|
+
```
|
|
2040
|
+
|
|
2041
|
+
Optionally, you can pass a function into `.catch` that will be re-executed whenever a default value needs to be generated:
|
|
2042
|
+
|
|
2043
|
+
```ts
|
|
2044
|
+
const numberWithRandomCatch = z.number().catch(Math.random);
|
|
2045
|
+
|
|
2046
|
+
numberWithRandomDefault.parse("sup"); // => 0.4413456736055323
|
|
2047
|
+
numberWithRandomDefault.parse("sup"); // => 0.1871840107401901
|
|
2048
|
+
numberWithRandomDefault.parse("sup"); // => 0.7223408162401552
|
|
2049
|
+
```
|
|
2050
|
+
|
|
2051
|
+
Conceptually, this is how Zod processes "catch values":
|
|
2052
|
+
|
|
2053
|
+
1. The data is parsed using the base schema
|
|
2054
|
+
2. If the parsing fails, the "catch value" is returned
|
|
2055
|
+
|
|
1818
2056
|
### `.optional`
|
|
1819
2057
|
|
|
1820
2058
|
A convenience method that returns an optional version of a schema.
|
|
@@ -1853,7 +2091,7 @@ z.string().optional().nullable();
|
|
|
1853
2091
|
A convenience method that returns an array schema for the given type:
|
|
1854
2092
|
|
|
1855
2093
|
```ts
|
|
1856
|
-
const
|
|
2094
|
+
const stringArray = z.string().array(); // string[]
|
|
1857
2095
|
|
|
1858
2096
|
// equivalent to
|
|
1859
2097
|
z.array(z.string());
|
|
@@ -1875,7 +2113,7 @@ z.promise(z.string());
|
|
|
1875
2113
|
A convenience method for union types.
|
|
1876
2114
|
|
|
1877
2115
|
```ts
|
|
1878
|
-
z.string().or(z.number()); // string | number
|
|
2116
|
+
const stringOrNumber = z.string().or(z.number()); // string | number
|
|
1879
2117
|
|
|
1880
2118
|
// equivalent to
|
|
1881
2119
|
z.union([z.string(), z.number()]);
|
|
@@ -1886,7 +2124,7 @@ z.union([z.string(), z.number()]);
|
|
|
1886
2124
|
A convenience method for creating intersection types.
|
|
1887
2125
|
|
|
1888
2126
|
```ts
|
|
1889
|
-
z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: string } & { age: number }
|
|
2127
|
+
const nameAndAge = z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: string } & { age: number }
|
|
1890
2128
|
|
|
1891
2129
|
// equivalent to
|
|
1892
2130
|
z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
|
@@ -1910,7 +2148,7 @@ petCat(fido); // works fine
|
|
|
1910
2148
|
In some cases, its can be desirable to simulate _nominal typing_ inside TypeScript. For instance, you may wish to write a function that only accepts an input that has been validated by Zod. This can be achieved with _branded types_ (AKA _opaque types_).
|
|
1911
2149
|
|
|
1912
2150
|
```ts
|
|
1913
|
-
const Cat = z.object({ name: z.string }).brand<"Cat">();
|
|
2151
|
+
const Cat = z.object({ name: z.string() }).brand<"Cat">();
|
|
1914
2152
|
type Cat = z.infer<typeof Cat>;
|
|
1915
2153
|
|
|
1916
2154
|
const petCat = (cat: Cat) => {};
|
|
@@ -1926,7 +2164,7 @@ petCat({ name: "fido" });
|
|
|
1926
2164
|
Under the hood, this works by attaching a "brand" to the inferred type using an intersection type. This way, plain/unbranded data structures are no longer assignable to the inferred type of the schema.
|
|
1927
2165
|
|
|
1928
2166
|
```ts
|
|
1929
|
-
const Cat = z.object({ name: z.string }).brand<"Cat">();
|
|
2167
|
+
const Cat = z.object({ name: z.string() }).brand<"Cat">();
|
|
1930
2168
|
type Cat = z.infer<typeof Cat>;
|
|
1931
2169
|
// {name: string} & {[symbol]: "Cat"}
|
|
1932
2170
|
```
|
|
@@ -1966,7 +2204,7 @@ type inferred = z.infer<typeof stringToNumber>; // number
|
|
|
1966
2204
|
|
|
1967
2205
|
### Writing generic functions
|
|
1968
2206
|
|
|
1969
|
-
When attempting to write a
|
|
2207
|
+
When attempting to write a function that accepts a Zod schema as an input, it's common to try something like this:
|
|
1970
2208
|
|
|
1971
2209
|
```ts
|
|
1972
2210
|
function makeSchemaOptional<T>(schema: z.ZodType<T>) {
|
|
@@ -1981,7 +2219,7 @@ const arg = makeSchemaOptional(z.string());
|
|
|
1981
2219
|
arg.unwrap();
|
|
1982
2220
|
```
|
|
1983
2221
|
|
|
1984
|
-
A better approach is for the
|
|
2222
|
+
A better approach is for the generic parameter to refer to _the schema as a whole_.
|
|
1985
2223
|
|
|
1986
2224
|
```ts
|
|
1987
2225
|
function makeSchemaOptional<T extends z.ZodTypeAny>(schema: T) {
|
|
@@ -2051,6 +2289,8 @@ if (!data.success) {
|
|
|
2051
2289
|
|
|
2052
2290
|
> 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)
|
|
2053
2291
|
|
|
2292
|
+
Zod's error reporting emphasizes _completeness_ and _correctness_. If you are looking to present a useful error message to the end user, you should either override Zod's error messages using an error map (described in detail in the Error Handling guide) or use a third party library like [`zod-validation-error`](https://github.com/causaly/zod-validation-error)
|
|
2293
|
+
|
|
2054
2294
|
### Error formatting
|
|
2055
2295
|
|
|
2056
2296
|
You can use the `.format()` method to convert this error into a nested object.
|