zod 3.16.0 → 3.17.2

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