zod 3.20.2 → 3.20.6

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
@@ -47,10 +47,12 @@
47
47
  - [Sponsors](#sponsors)
48
48
  - [Ecosystem](#ecosystem)
49
49
  - [Installation](#installation)
50
- - [Node/npm](#nodenpm)
51
- - [Deno](#deno)
50
+ - [Requirements](#requirements)
51
+ - [Node/npm](#from-npm-nodebun)
52
+ - [Deno](#from-denolandx-deno)
52
53
  - [Basic usage](#basic-usage)
53
54
  - [Primitives](#primitives)
55
+ - [Coercion for primitives](#coercion-for-primitives)
54
56
  - [Literals](#literals)
55
57
  - [Strings](#strings)
56
58
  - [Numbers](#numbers)
@@ -101,6 +103,7 @@
101
103
  - [.superRefine](#superRefine)
102
104
  - [.transform](#transform)
103
105
  - [.default](#default)
106
+ - [.describe](#describe)
104
107
  - [.catch](#catch)
105
108
  - [.optional](#optional)
106
109
  - [.nullable](#nullable)
@@ -355,12 +358,15 @@ There are a growing number of tools that are built atop or support Zod natively!
355
358
  #### Form integrations
356
359
 
357
360
  - [`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
361
+ - [`zod-validation-error`](https://github.com/causaly/zod-validation-error): Generate user-friendly error messages from `ZodError`s.
359
362
  - [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod.
360
363
  - [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod.
361
364
  - [`zodix`](https://github.com/rileytomasek/zodix): Zod utilities for FormData and URLSearchParams in Remix loaders and actions.
365
+ - [`remix-params-helper`](https://github.com/kiliman/remix-params-helper): Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.
362
366
  - [`formik-validator-zod`](https://github.com/glazy/formik-validator-zod): Formik-compliant validator library that simplifies using Zod with Formik.
363
367
  - [`zod-i18n-map`](https://github.com/aiji42/zod-i18n): Useful for translating Zod error messages.
368
+ - [`@modular-forms/solid`](https://github.com/fabian-hiller/modular-forms): Modular form library for SolidJS that supports Zod for validation.
369
+ - [`houseform`](https://github.com/crutchcorn/houseform/): A React form library that uses Zod for validation.
364
370
 
365
371
  #### Zod to X
366
372
 
@@ -379,15 +385,16 @@ There are a growing number of tools that are built atop or support Zod natively!
379
385
  - [`@runtyping/zod`](https://github.com/johngeorgewright/runtyping/tree/master/packages/zod): Generate Zod from static types & JSON schema.
380
386
  - [`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/).
381
387
  - [`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/).
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
388
+ - [`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.
383
389
  - [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema.
384
390
  - [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs.
385
391
  - [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
386
392
  - [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
393
+ - [`zod-prisma-types`](https://github.com/chrishoermann/zod-prisma-types) Create Zod types from your Prisma models.
387
394
 
388
395
  #### Mocking
389
396
 
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).
397
+ - [`@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/faker-js/faker).
391
398
  - [`zod-mocking`](https://github.com/dipasqualew/zod-mocking): Generate mock data from your Zod schemas.
392
399
 
393
400
  #### Powered by Zod
@@ -395,7 +402,11 @@ There are a growing number of tools that are built atop or support Zod natively!
395
402
  - [`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
403
  - [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
397
404
  - [`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
405
+ - [`znv`](https://github.com/lostfictions/znv): Type-safe environment parsing and validation for Node.js with Zod schemas.
406
+
407
+ #### Utilities for Zod
408
+
409
+ - [`zod_utilz`](https://github.com/JacobWeisenburger/zod_utilz): Framework agnostic utilities for Zod.
399
410
 
400
411
  ## Installation
401
412
 
@@ -503,8 +514,53 @@ z.unknown();
503
514
  z.never();
504
515
  ```
505
516
 
517
+ ## Coercion for primitives
518
+
519
+ Zod now provides a more convenient way to coerce primitive values.
520
+
521
+ ```ts
522
+ const schema = z.coerce.string();
523
+ schema.parse("tuna"); // => "tuna"
524
+ schema.parse(12); // => "12"
525
+ schema.parse(true); // => "true"
526
+ ```
527
+
528
+ 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.
529
+
530
+ ```ts
531
+ z.coerce.string().email().min(5);
532
+ ```
533
+
534
+ All primitive types support coercion.
535
+
536
+ ```ts
537
+ z.coerce.string(); // String(input)
538
+ z.coerce.number(); // Number(input)
539
+ z.coerce.boolean(); // Boolean(input)
540
+ z.coerce.bigint(); // BigInt(input)
541
+ z.coerce.date(); // new Date(input)
542
+ ```
543
+
544
+ **Boolean coercion**
545
+
546
+ Zod's boolean coercion is very simple! It passes the value into the `Boolean(value)` function, that's it. Any truthy value will resolve to `true`, any falsy value will resolve to `false`.
547
+
548
+ ```ts
549
+ z.coerce.boolean().parse("tuna"); // => true
550
+ z.coerce.boolean().parse("true"); // => true
551
+ z.coerce.boolean().parse("false"); // => true
552
+ z.coerce.boolean().parse(1); // => true
553
+ z.coerce.boolean().parse([]); // => true
554
+
555
+ z.coerce.boolean().parse(0); // => false
556
+ z.coerce.boolean().parse(undefined); // => false
557
+ z.coerce.boolean().parse(null); // => false
558
+ ```
559
+
506
560
  ## Literals
507
561
 
562
+ Literal schemas represent a [literal type](https://www.typescriptlang.org/docs/handbook/literal-types.html), like `"hello world"` or `5`.
563
+
508
564
  ```ts
509
565
  const tuna = z.literal("tuna");
510
566
  const twelve = z.literal(12);
@@ -532,6 +588,7 @@ z.string().email();
532
588
  z.string().url();
533
589
  z.string().uuid();
534
590
  z.string().cuid();
591
+ z.string().cuid2();
535
592
  z.string().regex(regex);
536
593
  z.string().startsWith(string);
537
594
  z.string().endsWith(string);
@@ -564,49 +621,6 @@ z.string().endsWith(".com", { message: "Only .com domains allowed" });
564
621
  z.string().datetime({ message: "Invalid datetime string! Must be UTC." });
565
622
  ```
566
623
 
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
- **Boolean coercion**
595
-
596
- Zod's boolean coercion is very simple! It passes the value into the `Boolean(value)` function, that's it. Any truthy value will resolve to `true`, any falsy value will resolve to `false`.
597
-
598
- ```ts
599
- z.coerce.boolean().parse("tuna"); // => true
600
- z.coerce.boolean().parse("true"); // => true
601
- z.coerce.boolean().parse("false"); // => true
602
- z.coerce.boolean().parse(1); // => true
603
- z.coerce.boolean().parse([]); // => true
604
-
605
- z.coerce.boolean().parse(0); // => false
606
- z.coerce.boolean().parse(undefined); // => false
607
- z.coerce.boolean().parse(null); // => false
608
- ```
609
-
610
624
  ### Datetime validation
611
625
 
612
626
  The `z.string().datetime()` method defaults to UTC validation: no timezone offsets with arbitrary sub-second decimal precision.
@@ -627,6 +641,8 @@ const datetime = z.string().datetime({ offset: true });
627
641
 
628
642
  datetime.parse("2020-01-01T00:00:00+02:00"); // pass
629
643
  datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional)
644
+ datetime.parse("2020-01-01T00:00:00.123+0200"); // pass (millis optional)
645
+ datetime.parse("2020-01-01T00:00:00.123+02"); // pass (only offset hours)
630
646
  datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported)
631
647
  ```
632
648
 
@@ -724,21 +740,28 @@ z.date().min(new Date("1900-01-01"), { message: "Too old" });
724
740
  z.date().max(new Date(), { message: "Too young!" });
725
741
  ```
726
742
 
727
- **Supporting date strings**
743
+ **Coercion to Date**
728
744
 
729
- To write a schema that accepts either a `Date` or a date string, use [`z.preprocess`](#preprocess).
745
+ Since [zod 3.20](https://github.com/colinhacks/zod/releases/tag/v3.20), use [`z.coerce.date()`](#coercion-for-primitives) to pass the input through `new Date(input)`.
730
746
 
731
747
  ```ts
732
- const dateSchema = z.preprocess((arg) => {
733
- if (typeof arg == "string" || arg instanceof Date) return new Date(arg);
734
- }, z.date());
748
+ const dateSchema = z.coerce.date();
735
749
  type DateSchema = z.infer<typeof dateSchema>;
736
750
  // type DateSchema = Date
737
751
 
738
- dateSchema.safeParse(new Date("1/12/22")); // success: true
739
- dateSchema.safeParse("2022-01-12T00:00:00.000Z"); // success: true
752
+ /* valid dates */
753
+ console.log(dateSchema.safeParse("2023-01-10T00:00:00.000Z").success); // true
754
+ console.log(dateSchema.safeParse("2023-01-10").success); // true
755
+ console.log(dateSchema.safeParse("1/10/23").success); // true
756
+ console.log(dateSchema.safeParse(new Date("1/10/23")).success); // true
757
+
758
+ /* invalid dates */
759
+ console.log(dateSchema.safeParse("2023-13-10").success); // false
760
+ console.log(dateSchema.safeParse("0000-00-00").success); // false
740
761
  ```
741
762
 
763
+ For older zod versions, use [`z.preprocess`](#preprocess) like [described in this thread](https://github.com/colinhacks/zod/discussions/879#discussioncomment-2036276).
764
+
742
765
  ## Zod enums
743
766
 
744
767
  ```ts
@@ -781,7 +804,7 @@ FishEnum.enum;
781
804
  You can also retrieve the list of options as a tuple with the `.options` property:
782
805
 
783
806
  ```ts
784
- FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
807
+ FishEnum.options; // ["Salmon", "Tuna", "Trout"];
785
808
  ```
786
809
 
787
810
  ## Native enums
@@ -1265,12 +1288,28 @@ stringOrNumber.parse(14); // passes
1265
1288
 
1266
1289
  Zod will test the input against each of the "options" in order and return the first value that validates successfully.
1267
1290
 
1268
- For convenience, you can also use the `.or` method:
1291
+ For convenience, you can also use the [`.or` method](#or):
1269
1292
 
1270
1293
  ```ts
1271
1294
  const stringOrNumber = z.string().or(z.number());
1272
1295
  ```
1273
1296
 
1297
+ **Optional string validation:**
1298
+
1299
+ To validate an optional form input, you can union the desired string validation with an empty string [literal](#literals).
1300
+
1301
+ This example validates an input that is optional but needs to contain a [valid URL](#strings):
1302
+
1303
+ ```ts
1304
+ const optionalUrl = z.union([z.string().url().nullish(), z.literal("")]);
1305
+
1306
+ console.log(optionalUrl.safeParse(undefined).success); // true
1307
+ console.log(optionalUrl.safeParse(null).success); // true
1308
+ console.log(optionalUrl.safeParse("").success); // true
1309
+ console.log(optionalUrl.safeParse("https://zod.dev").success); // true
1310
+ console.log(optionalUrl.safeParse("not a valid url").success); // false
1311
+ ```
1312
+
1274
1313
  ## Discriminated unions
1275
1314
 
1276
1315
  A discriminated union is a union of object schemas that all share a particular key.
@@ -1283,7 +1322,7 @@ type MyUnion =
1283
1322
 
1284
1323
  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.
1285
1324
 
1286
- 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".
1325
+ 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".
1287
1326
 
1288
1327
  ```ts
1289
1328
  const myUnion = z.discriminatedUnion("status", [
@@ -1291,7 +1330,7 @@ const myUnion = z.discriminatedUnion("status", [
1291
1330
  z.object({ status: z.literal("failed"), error: z.instanceof(Error) }),
1292
1331
  ]);
1293
1332
 
1294
- myUnion.parse({ type: "success", data: "yippie ki yay" });
1333
+ myUnion.parse({ status: "success", data: "yippie ki yay" });
1295
1334
  ```
1296
1335
 
1297
1336
  ## Records
@@ -1432,55 +1471,67 @@ type Teacher = z.infer<typeof Teacher>;
1432
1471
  You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".
1433
1472
 
1434
1473
  ```ts
1435
- interface Category {
1436
- name: string;
1474
+ const baseCategorySchema = z.object({
1475
+ name: z.string(),
1476
+ });
1477
+
1478
+ type Category = z.infer<typeof baseCategorySchema> & {
1437
1479
  subcategories: Category[];
1438
- }
1480
+ };
1439
1481
 
1440
- // cast to z.ZodType<Category>
1441
- const Category: z.ZodType<Category> = z.lazy(() =>
1442
- z.object({
1443
- name: z.string(),
1444
- subcategories: z.array(Category),
1445
- })
1446
- );
1482
+ const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
1483
+ subcategories: z.lazy(() => categorySchema.array()),
1484
+ });
1447
1485
 
1448
- Category.parse({
1486
+ categorySchema.parse({
1449
1487
  name: "People",
1450
1488
  subcategories: [
1451
1489
  {
1452
1490
  name: "Politicians",
1453
- subcategories: [{ name: "Presidents", subcategories: [] }],
1491
+ subcategories: [
1492
+ {
1493
+ name: "Presidents",
1494
+ subcategories: [],
1495
+ },
1496
+ ],
1454
1497
  },
1455
1498
  ],
1456
1499
  }); // passes
1457
1500
  ```
1458
1501
 
1459
- Unfortunately this code is a bit duplicative, since you're declaring the types twice: once in the interface and again in the Zod definition.
1502
+ Thanks to [crasite](https://github.com/crasite) for this example.
1503
+
1504
+ ### ZodType with ZodEffects
1460
1505
 
1461
- <!-- If your schema has lots of primitive fields, there's a way of reducing the amount of duplication:
1506
+ When using `z.ZodType` with `z.ZodEffects` (
1507
+ [`.refine`](https://github.com/colinhacks/zod#refine),
1508
+ [`.transform`](https://github.com/colinhacks/zod#transform),
1509
+ [`preprocess`](https://github.com/colinhacks/zod#preprocess),
1510
+ etc...
1511
+ ), you will need to define the input and output types of the schema. `z.ZodType<Output, z.ZodTypeDef, Input>`
1462
1512
 
1463
1513
  ```ts
1464
- // define all the non-recursive stuff here
1465
- const BaseCategory = z.object({
1466
- name: z.string(),
1467
- tags: z.array(z.string()),
1468
- itemCount: z.number(),
1514
+ const isValidId = (id: string): id is `${string}/${string}` =>
1515
+ id.split("/").length === 2;
1516
+
1517
+ const baseSchema = z.object({
1518
+ id: z.string().refine(isValidId),
1469
1519
  });
1470
1520
 
1471
- // create an interface that extends the base schema
1472
- interface Category extends z.infer<typeof BaseCategory> {
1473
- subcategories: Category[];
1474
- }
1521
+ type Input = z.input<typeof baseSchema> & {
1522
+ children: Input[];
1523
+ };
1475
1524
 
1476
- // merge the base schema with
1477
- // a new Zod schema containing relations
1478
- const Category: z.ZodType<Category> = BaseCategory.merge(
1479
- z.object({
1480
- subcategories: z.lazy(() => z.array(Category)),
1481
- })
1482
- );
1483
- ``` -->
1525
+ type Output = z.output<typeof baseSchema> & {
1526
+ children: Output[];
1527
+ };
1528
+
1529
+ const schema: z.ZodType<Output, z.ZodTypeDef, Input> = baseSchema.extend({
1530
+ children: z.lazy(() => schema.array()),
1531
+ });
1532
+ ```
1533
+
1534
+ Thanks to [marcus13371337](https://github.com/marcus13371337) and [JoelBeeldi](https://github.com/JoelBeeldi) for this example.
1484
1535
 
1485
1536
  ### JSON type
1486
1537
 
@@ -1679,21 +1730,20 @@ Given any Zod schema, you can call its `.parse` method to check `data` is valid.
1679
1730
  const stringSchema = z.string();
1680
1731
 
1681
1732
  stringSchema.parse("fish"); // => returns "fish"
1682
- stringSchema.parse(12); // throws Error('Non-string type: number');
1733
+ stringSchema.parse(12); // throws error
1683
1734
  ```
1684
1735
 
1685
1736
  ### `.parseAsync`
1686
1737
 
1687
1738
  `.parseAsync(data:unknown): Promise<T>`
1688
1739
 
1689
- If you use asynchronous [refinements](#refine) or [transforms](#transform) (more on those later), you'll need to use `.parseAsync`
1740
+ If you use asynchronous [refinements](#refine) or [transforms](#transform) (more on those later), you'll need to use `.parseAsync`.
1690
1741
 
1691
1742
  ```ts
1692
- const stringSchema1 = z.string().refine(async (val) => val.length < 20);
1693
- const value1 = await stringSchema.parseAsync("hello"); // => hello
1743
+ const stringSchema = z.string().refine(async (val) => val.length <= 8);
1694
1744
 
1695
- const stringSchema2 = z.string().refine(async (val) => val.length > 20);
1696
- const value2 = await stringSchema.parseAsync("hello"); // => throws
1745
+ await stringSchema.parseAsync("hello"); // => returns "hello"
1746
+ await stringSchema.parseAsync("hello world"); // => throws error
1697
1747
  ```
1698
1748
 
1699
1749
  ### `.safeParse`
@@ -1710,7 +1760,7 @@ stringSchema.safeParse("billie");
1710
1760
  // => { success: true; data: 'billie' }
1711
1761
  ```
1712
1762
 
1713
- The result is a _discriminated union_ so you can handle errors very conveniently:
1763
+ The result is a _discriminated union_, so you can handle errors very conveniently:
1714
1764
 
1715
1765
  ```ts
1716
1766
  const result = stringSchema.safeParse("billie");
@@ -1778,7 +1828,7 @@ type RefineParams = {
1778
1828
  };
1779
1829
  ```
1780
1830
 
1781
- For advanced cases, the second argument can also be a function that returns `RefineParams`/
1831
+ For advanced cases, the second argument can also be a function that returns `RefineParams`.
1782
1832
 
1783
1833
  ```ts
1784
1834
  const longString = z.string().refine(
@@ -1889,7 +1939,7 @@ const Strings = z.array(z.string()).superRefine((val, ctx) => {
1889
1939
 
1890
1940
  You can add as many issues as you like. If `ctx.addIssue` is _not_ called during the execution of the function, validation passes.
1891
1941
 
1892
- Normally refinements always create issues with a `ZodIssueCode.custom` error code, but with `superRefine` you can create any issue of any code. Each issue code is described in detail in the Error Handling guide: [ERROR_HANDLING.md](ERROR_HANDLING.md).
1942
+ Normally refinements always create issues with a `ZodIssueCode.custom` error code, but with `superRefine` it's possible to throw issues of any `ZodIssueCode`. Each issue code is described in detail in the Error Handling guide: [ERROR_HANDLING.md](ERROR_HANDLING.md).
1893
1943
 
1894
1944
  #### Abort early
1895
1945
 
@@ -1918,7 +1968,7 @@ const schema = z.number().superRefine((val, ctx) => {
1918
1968
 
1919
1969
  #### Type refinements
1920
1970
 
1921
- 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:
1971
+ 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:
1922
1972
 
1923
1973
  ```ts
1924
1974
  const schema = z
@@ -1933,15 +1983,15 @@ const schema = z
1933
1983
  code: z.ZodIssueCode.custom, // customize your issue
1934
1984
  message: "object should exist",
1935
1985
  });
1936
- return false;
1937
1986
  }
1938
- return true;
1987
+
1988
+ return z.NEVER; // The return value is not used, but we need to return something to satisfy the typing
1939
1989
  })
1940
1990
  // here, TS knows that arg is not null
1941
1991
  .refine((arg) => arg.first === "bob", "`first` is not `bob`!");
1942
1992
  ```
1943
1993
 
1944
- > ⚠️ You must **still** call `ctx.addIssue()` if using `superRefine()` with a type predicate function. Otherwise the refinement won't be validated.
1994
+ > ⚠️ You **must** use `ctx.addIssue()` instead of returning a boolean value to indicate whether the validation passes. If `ctx.addIssue` is _not_ called during the execution of the function, validation passes.
1945
1995
 
1946
1996
  ### `.transform`
1947
1997
 
@@ -1968,12 +2018,12 @@ emailToDomain.parse("colinhacks@example.com"); // => example.com
1968
2018
 
1969
2019
  #### Validating during transform
1970
2020
 
1971
- The `.transform` method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining `refine` and `validate`.
2021
+ The `.transform` method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining `transform` and `refine`.
1972
2022
 
1973
- As with `.superRefine`, the transform function receives a `ctx` object with a `addIssue` method that can be used to register validation issues.
2023
+ As with `.superRefine`, the transform function receives a `ctx` object with an `addIssue` method that can be used to register validation issues.
1974
2024
 
1975
2025
  ```ts
1976
- const Strings = z.string().transform((val, ctx) => {
2026
+ const numberInString = z.string().transform((val, ctx) => {
1977
2027
  const parsed = parseInt(val);
1978
2028
  if (isNaN(parsed)) {
1979
2029
  ctx.addIssue({
@@ -2044,6 +2094,19 @@ Conceptually, this is how Zod processes default values:
2044
2094
  1. If the input is `undefined`, the default value is returned
2045
2095
  2. Otherwise, the data is parsed using the base schema
2046
2096
 
2097
+ ### `.describe`
2098
+
2099
+ Use `.describe()` to add a `description` property to the resulting schema.
2100
+
2101
+ ```ts
2102
+ const documentedString = z
2103
+ .string()
2104
+ .describe("A useful bit of text, if you know what to do with it.");
2105
+ documentedString.description; // A useful bit of text…
2106
+ ```
2107
+
2108
+ This can be useful for documenting a field, for example in a JSON Schema using a library like [`zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema)).
2109
+
2047
2110
  ### `.catch`
2048
2111
 
2049
2112
  Use `.catch()` to provide a "catch value" to be returned in the event of a parsing error.
@@ -2127,7 +2190,7 @@ z.promise(z.string());
2127
2190
 
2128
2191
  ### `.or`
2129
2192
 
2130
- A convenience method for union types.
2193
+ A convenience method for [union types](#unions).
2131
2194
 
2132
2195
  ```ts
2133
2196
  const stringOrNumber = z.string().or(z.number()); // string | number
@@ -2308,7 +2371,7 @@ if (!data.success) {
2308
2371
 
2309
2372
  > 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)
2310
2373
 
2311
- 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)
2374
+ 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)
2312
2375
 
2313
2376
  ### Error formatting
2314
2377
 
@@ -2461,7 +2524,7 @@ This more declarative API makes schema definitions vastly more concise.
2461
2524
 
2462
2525
  [https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
2463
2526
 
2464
- Good type inference support, but limited options for object type masking (no `.pick` , `.omit` , `.extend` , etc.). No support for `Record` s (their `Record` is equivalent to Zod's `object` ). They DO support branded and readonly types, which Zod does not.
2527
+ Good type inference support, but limited options for object type masking (no `.pick` , `.omit` , `.extend` , etc.). No support for `Record` s (their `Record` is equivalent to Zod's `object` ). They DO support readonly types, which Zod does not.
2465
2528
 
2466
2529
  - Supports "pattern matching": computed properties that distribute over unions
2467
2530
  - Supports readonly types
package/lib/ZodError.d.ts CHANGED
@@ -40,6 +40,7 @@ export interface ZodInvalidTypeIssue extends ZodIssueBase {
40
40
  export interface ZodInvalidLiteralIssue extends ZodIssueBase {
41
41
  code: typeof ZodIssueCode.invalid_literal;
42
42
  expected: unknown;
43
+ received: unknown;
43
44
  }
44
45
  export interface ZodUnrecognizedKeysIssue extends ZodIssueBase {
45
46
  code: typeof ZodIssueCode.unrecognized_keys;
@@ -69,7 +70,7 @@ export interface ZodInvalidReturnTypeIssue extends ZodIssueBase {
69
70
  export interface ZodInvalidDateIssue extends ZodIssueBase {
70
71
  code: typeof ZodIssueCode.invalid_date;
71
72
  }
72
- export declare type StringValidation = "email" | "url" | "uuid" | "regex" | "cuid" | "datetime" | {
73
+ export declare type StringValidation = "email" | "url" | "uuid" | "regex" | "cuid" | "cuid2" | "datetime" | {
73
74
  startsWith: string;
74
75
  } | {
75
76
  endsWith: string;
@@ -120,11 +121,11 @@ export declare const quotelessJson: (obj: any) => string;
120
121
  export declare type ZodFormattedError<T, U = string> = {
121
122
  _errors: U[];
122
123
  } & (NonNullable<T> extends [any, ...any[]] ? {
123
- [K in keyof NonNullable<T>]?: ZodFormattedError<NonNullable<T>[K]>;
124
+ [K in keyof NonNullable<T>]?: ZodFormattedError<NonNullable<T>[K], U>;
124
125
  } : NonNullable<T> extends any[] ? {
125
- [k: number]: ZodFormattedError<NonNullable<T>[number]>;
126
+ [k: number]: ZodFormattedError<NonNullable<T>[number], U>;
126
127
  } : NonNullable<T> extends object ? {
127
- [K in keyof NonNullable<T>]?: ZodFormattedError<NonNullable<T>[K]>;
128
+ [K in keyof NonNullable<T>]?: ZodFormattedError<NonNullable<T>[K], U>;
128
129
  } : unknown);
129
130
  export declare type inferFormattedError<T extends ZodType<any, any, any>, U = string> = ZodFormattedError<TypeOf<T>, U>;
130
131
  export declare class ZodError<T = any> extends Error {
@@ -0,0 +1,17 @@
1
+ export declare class Mocker {
2
+ pick: (...args: any[]) => any;
3
+ get string(): string;
4
+ get number(): number;
5
+ get bigint(): bigint;
6
+ get boolean(): boolean;
7
+ get date(): Date;
8
+ get symbol(): symbol;
9
+ get null(): null;
10
+ get undefined(): undefined;
11
+ get stringOptional(): any;
12
+ get stringNullable(): any;
13
+ get numberOptional(): any;
14
+ get numberNullable(): any;
15
+ get booleanOptional(): any;
16
+ get booleanNullable(): any;
17
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Mocker = void 0;
4
+ function getRandomInt(max) {
5
+ return Math.floor(Math.random() * Math.floor(max));
6
+ }
7
+ const testSymbol = Symbol("test");
8
+ class Mocker {
9
+ constructor() {
10
+ this.pick = (...args) => {
11
+ return args[getRandomInt(args.length)];
12
+ };
13
+ }
14
+ get string() {
15
+ return Math.random().toString(36).substring(7);
16
+ }
17
+ get number() {
18
+ return Math.random() * 100;
19
+ }
20
+ get bigint() {
21
+ return BigInt(Math.floor(Math.random() * 10000));
22
+ }
23
+ get boolean() {
24
+ return Math.random() < 0.5;
25
+ }
26
+ get date() {
27
+ return new Date(Math.floor(Date.now() * Math.random()));
28
+ }
29
+ get symbol() {
30
+ return testSymbol;
31
+ }
32
+ get null() {
33
+ return null;
34
+ }
35
+ get undefined() {
36
+ return undefined;
37
+ }
38
+ get stringOptional() {
39
+ return this.pick(this.string, this.undefined);
40
+ }
41
+ get stringNullable() {
42
+ return this.pick(this.string, this.null);
43
+ }
44
+ get numberOptional() {
45
+ return this.pick(this.number, this.undefined);
46
+ }
47
+ get numberNullable() {
48
+ return this.pick(this.number, this.null);
49
+ }
50
+ get booleanOptional() {
51
+ return this.pick(this.boolean, this.undefined);
52
+ }
53
+ get booleanNullable() {
54
+ return this.pick(this.boolean, this.null);
55
+ }
56
+ }
57
+ exports.Mocker = Mocker;