zod 3.15.1 → 3.17.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 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
@@ -293,14 +278,61 @@ There are a growing number of tools that are built atop or support Zod natively!
293
278
  - [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas
294
279
  - [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs
295
280
  - [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters
281
+ - [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
282
+ - [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
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.
296
284
 
297
- ### Form integrations
285
+ #### Form integrations
298
286
 
299
287
  - [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form
300
288
  - [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod
301
289
  - [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod
302
290
 
303
- # 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
304
336
 
305
337
  Creating a simple string schema
306
338
 
@@ -335,8 +367,6 @@ type User = z.infer<typeof User>;
335
367
  // { username: string }
336
368
  ```
337
369
 
338
- # Defining schemas
339
-
340
370
  ## Primitives
341
371
 
342
372
  ```ts
@@ -391,6 +421,9 @@ z.string().uuid();
391
421
  z.string().cuid();
392
422
  z.string().regex(regex);
393
423
 
424
+ // trim whitespace
425
+ z.string().trim();
426
+
394
427
  // deprecated, equivalent to .min(1)
395
428
  z.string().nonempty();
396
429
 
@@ -400,9 +433,7 @@ z.string().nonempty({ message: "Can't be empty" });
400
433
 
401
434
  > Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
402
435
 
403
- #### Custom error messages
404
-
405
- You can customize certain errors when creating a string schema.
436
+ You can customize some common errors messages when creating a string schema.
406
437
 
407
438
  ```ts
408
439
  const name = z.string({
@@ -548,7 +579,7 @@ FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
548
579
 
549
580
  ## Native enums
550
581
 
551
- Zod enums are the recommended approach to defining and validating enums. But if you need to validate against an enum from a third-party library (or you don't want to rewrite your existing enums) you can use `z.nativeEnum()` .
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()`.
552
583
 
553
584
  **Numeric enums**
554
585
 
@@ -616,7 +647,7 @@ FruitEnum.enum.Apple; // "apple"
616
647
 
617
648
  ## Optionals
618
649
 
619
- 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.
620
651
 
621
652
  ```ts
622
653
  const schema = z.optional(z.string());
@@ -625,7 +656,7 @@ schema.parse(undefined); // => returns undefined
625
656
  type A = z.infer<typeof schema>; // string | undefined
626
657
  ```
627
658
 
628
- 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.
629
660
 
630
661
  ```ts
631
662
  const user = z.object({
@@ -634,7 +665,7 @@ const user = z.object({
634
665
  type C = z.infer<typeof user>; // { username?: string | undefined };
635
666
  ```
636
667
 
637
- #### `.unwrap`
668
+ You can extract the wrapped schema from a `ZodOptional` instance with `.unwrap()`.
638
669
 
639
670
  ```ts
640
671
  const stringSchema = z.string();
@@ -644,7 +675,7 @@ optionalString.unwrap() === stringSchema; // true
644
675
 
645
676
  ## Nullables
646
677
 
647
- Similarly, you can create nullable types like so:
678
+ Similarly, you can create nullable types with `z.nullable()`.
648
679
 
649
680
  ```ts
650
681
  const nullableString = z.nullable(z.string());
@@ -652,14 +683,14 @@ nullableString.parse("asdf"); // => "asdf"
652
683
  nullableString.parse(null); // => null
653
684
  ```
654
685
 
655
- You can make an existing schema nullable with the `nullable` method:
686
+ Or use the `.nullable()` method.
656
687
 
657
688
  ```ts
658
689
  const E = z.string().nullable(); // equivalent to D
659
690
  type E = z.infer<typeof E>; // string | null
660
691
  ```
661
692
 
662
- #### `.unwrap`
693
+ Extract the inner schema with `.unwrap()`.
663
694
 
664
695
  ```ts
665
696
  const stringSchema = z.string();
@@ -815,7 +846,7 @@ const deepPartialUser = user.deepPartial();
815
846
 
816
847
  > Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.
817
848
 
818
- #### Unrecognized keys
849
+ ### `.passthrough`
819
850
 
820
851
  By default Zod objects schemas strip out unrecognized keys during parsing.
821
852
 
@@ -832,8 +863,6 @@ person.parse({
832
863
  // extraKey has been stripped
833
864
  ```
834
865
 
835
- ### `.passthrough`
836
-
837
866
  Instead, if you want to pass through unknown keys, use `.passthrough()` .
838
867
 
839
868
  ```ts
@@ -846,7 +875,7 @@ person.passthrough().parse({
846
875
 
847
876
  ### `.strict`
848
877
 
849
- 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.
850
879
 
851
880
  ```ts
852
881
  const person = z
@@ -983,7 +1012,7 @@ For convenience, you can also use the `.or` method:
983
1012
  const stringOrNumber = z.string().or(z.number());
984
1013
  ```
985
1014
 
986
- ### Discriminated unions
1015
+ ## Discriminated unions
987
1016
 
988
1017
  If the union consists of object schemas all identifiable by a common property, it is possible to use
989
1018
  the `z.discriminatedUnion` method.
@@ -1029,7 +1058,7 @@ userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
1029
1058
  }; // TypeError
1030
1059
  ```
1031
1060
 
1032
- #### A note on numerical keys
1061
+ **A note on numerical keys**
1033
1062
 
1034
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?
1035
1064
 
@@ -1046,9 +1075,7 @@ for (const key in testMap) {
1046
1075
  // prints: `1: string`
1047
1076
  ```
1048
1077
 
1049
- As you can see, JavaScript automatically casts all object keys to strings under the hood.
1050
-
1051
- Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.
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.
1052
1079
 
1053
1080
  ## Maps
1054
1081
 
@@ -1067,7 +1094,7 @@ type NumberSet = z.infer<typeof numberSet>;
1067
1094
  // type NumberSet = Set<number>
1068
1095
  ```
1069
1096
 
1070
- ### `.nonempty/.min/.max/.size`
1097
+ Set schemas can be further contrainted with the following utility methods.
1071
1098
 
1072
1099
  ```ts
1073
1100
  z.set(z.string()).nonempty(); // must contain at least one item
@@ -1078,8 +1105,6 @@ z.set(z.string()).size(5); // must contain 5 items exactly
1078
1105
 
1079
1106
  ## Intersections
1080
1107
 
1081
- <!-- > ⚠️ Intersections are deprecated. If you are trying to merge objects, use the `.merge` method instead. -->
1082
-
1083
1108
  Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.
1084
1109
 
1085
1110
  ```ts
@@ -1181,7 +1206,7 @@ const Category: z.ZodType<Category> = BaseCategory.merge(
1181
1206
  );
1182
1207
  ``` -->
1183
1208
 
1184
- #### JSON type
1209
+ ### JSON type
1185
1210
 
1186
1211
  If you want to validate any JSON value, you can use the snippet below.
1187
1212
 
@@ -1198,7 +1223,7 @@ jsonSchema.parse(data);
1198
1223
 
1199
1224
  Thanks to [ggoodman](https://github.com/ggoodman) for suggesting this.
1200
1225
 
1201
- #### Cyclical objects
1226
+ ### Cyclical objects
1202
1227
 
1203
1228
  Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop.
1204
1229
 
@@ -1262,7 +1287,7 @@ type myFunction = z.infer<typeof myFunction>;
1262
1287
  // => ()=>unknown
1263
1288
  ```
1264
1289
 
1265
- **Define inputs and output**
1290
+ Define inputs and outputs.
1266
1291
 
1267
1292
  ```ts
1268
1293
  const myFunction = z
@@ -1273,24 +1298,6 @@ type myFunction = z.infer<typeof myFunction>;
1273
1298
  // => (arg0: string, arg1: number)=>boolean
1274
1299
  ```
1275
1300
 
1276
- **Extract the input and output schemas**
1277
- You can extract the parameters and return type of a function schema.
1278
-
1279
- ```ts
1280
- myFunction.parameters();
1281
- // => ZodTuple<[ZodString, ZodNumber]>
1282
-
1283
- myFunction.returnType();
1284
- // => ZodBoolean
1285
- ```
1286
-
1287
- <!-- `z.function()` accepts two arguments:
1288
-
1289
- * `args: ZodTuple` The first argument is a tuple (created with `z.tuple([...])` and defines the schema of the arguments to your function. If the function doesn't accept arguments, you can pass an empty tuple (`z.tuple([])`).
1290
- * `returnType: any Zod schema` The second argument is the function's return type. This can be any Zod schema. -->
1291
-
1292
- > You can use the special `z.void()` option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)
1293
-
1294
1301
  <!--
1295
1302
 
1296
1303
  ``` ts
@@ -1319,7 +1326,9 @@ trimmedLength("sandwich"); // => 8
1319
1326
  trimmedLength(" asdf "); // => 4
1320
1327
  ```
1321
1328
 
1322
- 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.)
1323
1332
 
1324
1333
  ```ts
1325
1334
  const myFunction = z
@@ -1331,6 +1340,21 @@ const myFunction = z
1331
1340
  myFunction; // (arg: string)=>number[]
1332
1341
  ```
1333
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
+
1334
1358
  ## Preprocess
1335
1359
 
1336
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).)
@@ -1343,7 +1367,7 @@ const castToString = z.preprocess((val) => String(val), z.string());
1343
1367
 
1344
1368
  This returns a `ZodEffects` instance. `ZodEffects` is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.
1345
1369
 
1346
- # ZodType: methods and properties
1370
+ ## Schema methods
1347
1371
 
1348
1372
  All Zod schemas contain certain methods.
1349
1373
 
@@ -1368,8 +1392,11 @@ stringSchema.parse(12); // throws Error('Non-string type: number');
1368
1392
  If you use asynchronous [refinements](#refine) or [transforms](#transform) (more on those later), you'll need to use `.parseAsync`
1369
1393
 
1370
1394
  ```ts
1371
- const stringSchema = z.string().refine(async (val) => val.length > 20);
1372
- 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
1373
1400
  ```
1374
1401
 
1375
1402
  ### `.safeParse`
@@ -1602,7 +1629,7 @@ const stringToNumber = z.string().transform((val) => myString.length);
1602
1629
  stringToNumber.parse("string"); // => 6
1603
1630
  ```
1604
1631
 
1605
- > ⚠️ Transform functions must not throw. Make sure to use refinements before the transform to make sure the input can be parsed by the transform.
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.
1606
1633
 
1607
1634
  #### Chaining order
1608
1635
 
@@ -1617,14 +1644,33 @@ const emailToDomain = z
1617
1644
  emailToDomain.parse("colinhacks@example.com"); // => example.com
1618
1645
  ```
1619
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
+
1620
1664
  #### Relationship to refinements
1621
1665
 
1622
- Transforms and refinements can be interleaved:
1666
+ Transforms and refinements can be interleaved. These will be executed in the order they are declared.
1623
1667
 
1624
1668
  ```ts
1625
1669
  z.string()
1626
- .transform((val) => val.length)
1627
- .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);
1628
1674
  ```
1629
1675
 
1630
1676
  #### Async transforms
@@ -1686,7 +1732,7 @@ z.nullable(z.string());
1686
1732
 
1687
1733
  ### `.nullish`
1688
1734
 
1689
- A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both `undefined` and `null`. Read more about the concept of "nullish" [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).
1690
1736
 
1691
1737
  ```ts
1692
1738
  const nullishString = z.string().nullish(); // string | null | undefined
@@ -1739,9 +1785,9 @@ z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: st
1739
1785
  z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
1740
1786
  ```
1741
1787
 
1742
- # Guides and concepts
1788
+ ## Guides and concepts
1743
1789
 
1744
- ## Type inference
1790
+ ### Type inference
1745
1791
 
1746
1792
  You can extract the TypeScript type of any schema with `z.infer<typeof mySchema>` .
1747
1793
 
@@ -1753,7 +1799,7 @@ const u: A = 12; // TypeError
1753
1799
  const u: A = "asdf"; // compiles
1754
1800
  ```
1755
1801
 
1756
- #### What about transforms?
1802
+ **What about transforms?**
1757
1803
 
1758
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`.
1759
1805
 
@@ -1770,7 +1816,7 @@ type output = z.output<typeof stringToNumber>; // number
1770
1816
  type inferred = z.infer<typeof stringToNumber>; // number
1771
1817
  ```
1772
1818
 
1773
- ## Writing generic functions
1819
+ ### Writing generic functions
1774
1820
 
1775
1821
  When attempting to write a functions that accepts a Zod schemas as an input, it's common to try something like this:
1776
1822
 
@@ -1804,13 +1850,13 @@ const arg = makeSchemaOptional(z.string());
1804
1850
  arg.unwrap(); // ZodString
1805
1851
  ```
1806
1852
 
1807
- ### Restricting valid schemas
1853
+ #### Constraining allowable inputs
1808
1854
 
1809
1855
  The `ZodType` class has three generic parameters.
1810
1856
 
1811
1857
  ```ts
1812
1858
  class ZodType<
1813
- Output,
1859
+ Output = any,
1814
1860
  Def extends ZodTypeDef = ZodTypeDef,
1815
1861
  Input = Output
1816
1862
  > { ... }
@@ -1830,12 +1876,16 @@ makeSchemaOptional(z.number());
1830
1876
  // Error: 'ZodNumber' is not assignable to parameter of type 'ZodType<string, ZodTypeDef, string>'
1831
1877
  ```
1832
1878
 
1833
- ## Error handling
1879
+ ### Error handling
1834
1880
 
1835
1881
  Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.
1836
1882
 
1837
1883
  ```ts
1838
- 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 });
1839
1889
 
1840
1890
  if (!data.success) {
1841
1891
  data.error.issues;
@@ -1851,20 +1901,31 @@ if (!data.success) {
1851
1901
  }
1852
1902
  ```
1853
1903
 
1854
- #### 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
1855
1907
 
1856
1908
  You can use the `.format()` method to convert this error into a nested object.
1857
1909
 
1858
1910
  ```ts
1859
- data.error.format();
1860
- /* {
1861
- name: { _errors: [ 'Expected string, received number' ] }
1862
- } */
1863
- ```
1911
+ const data = z
1912
+ .object({
1913
+ name: z.string(),
1914
+ })
1915
+ .safeParse({ name: 12 });
1916
+
1917
+ if (!data.success) {
1918
+ const formatted = data.error.format();
1919
+ /* {
1920
+ name: { _errors: [ 'Expected string, received number' ] }
1921
+ } */
1864
1922
 
1865
- 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)
1923
+ formatted.name?._errors;
1924
+ // => ["Expected string, received number"]
1925
+ }
1926
+ ```
1866
1927
 
1867
- # Comparison
1928
+ ## Comparison
1868
1929
 
1869
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.
1870
1931
 
@@ -1916,20 +1977,18 @@ Branded -->
1916
1977
  * Missing support for parsing cyclical data (maybe)
1917
1978
  * Missing error customization -->
1918
1979
 
1919
- #### Joi
1980
+ **Joi**
1920
1981
 
1921
1982
  [https://github.com/hapijs/joi](https://github.com/hapijs/joi)
1922
1983
 
1923
1984
  Doesn't support static type inference 😕
1924
1985
 
1925
- #### Yup
1986
+ **Yup**
1926
1987
 
1927
1988
  [https://github.com/jquense/yup](https://github.com/jquense/yup)
1928
1989
 
1929
1990
  Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.
1930
1991
 
1931
- Differences
1932
-
1933
1992
  - Supports casting and transforms
1934
1993
  - All object fields are optional by default
1935
1994
  - Missing object methods: (partial, deepPartial)
@@ -1940,7 +1999,7 @@ Differences
1940
1999
 
1941
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. -->
1942
2001
 
1943
- #### io-ts
2002
+ **io-ts**
1944
2003
 
1945
2004
  [https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)
1946
2005
 
@@ -1991,7 +2050,7 @@ This more declarative API makes schema definitions vastly more concise.
1991
2050
  - Missing promise schemas
1992
2051
  - Missing function schemas
1993
2052
 
1994
- #### Runtypes
2053
+ **Runtypes**
1995
2054
 
1996
2055
  [https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
1997
2056
 
@@ -2004,7 +2063,7 @@ Good type inference support, but limited options for object type masking (no `.p
2004
2063
  - Missing promise schemas
2005
2064
  - Missing error customization
2006
2065
 
2007
- #### Ow
2066
+ **Ow**
2008
2067
 
2009
2068
  [https://github.com/sindresorhus/ow](https://github.com/sindresorhus/ow)
2010
2069
 
@@ -2012,6 +2071,6 @@ Ow is focused on function input validation. It's a library that makes it easy to
2012
2071
 
2013
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.
2014
2073
 
2015
- # Changelog
2074
+ ## Changelog
2016
2075
 
2017
2076
  View the changelog at [CHANGELOG.md](CHANGELOG.md)