zod 3.20.1 → 3.20.3

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,33 +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
624
  ### Datetime validation
595
625
 
596
626
  The `z.string().datetime()` method defaults to UTC validation: no timezone offsets with arbitrary sub-second decimal precision.
@@ -611,6 +641,8 @@ const datetime = z.string().datetime({ offset: true });
611
641
 
612
642
  datetime.parse("2020-01-01T00:00:00+02:00"); // pass
613
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)
614
646
  datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported)
615
647
  ```
616
648
 
@@ -708,21 +740,28 @@ z.date().min(new Date("1900-01-01"), { message: "Too old" });
708
740
  z.date().max(new Date(), { message: "Too young!" });
709
741
  ```
710
742
 
711
- **Supporting date strings**
743
+ **Coercion to Date**
712
744
 
713
- 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)`.
714
746
 
715
747
  ```ts
716
- const dateSchema = z.preprocess((arg) => {
717
- if (typeof arg == "string" || arg instanceof Date) return new Date(arg);
718
- }, z.date());
748
+ const dateSchema = z.coerce.date();
719
749
  type DateSchema = z.infer<typeof dateSchema>;
720
750
  // type DateSchema = Date
721
751
 
722
- dateSchema.safeParse(new Date("1/12/22")); // success: true
723
- 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
724
761
  ```
725
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
+
726
765
  ## Zod enums
727
766
 
728
767
  ```ts
@@ -765,7 +804,7 @@ FishEnum.enum;
765
804
  You can also retrieve the list of options as a tuple with the `.options` property:
766
805
 
767
806
  ```ts
768
- FishEnum.options; // ["Salmon", "Tuna", "Trout"]);
807
+ FishEnum.options; // ["Salmon", "Tuna", "Trout"];
769
808
  ```
770
809
 
771
810
  ## Native enums
@@ -1249,12 +1288,28 @@ stringOrNumber.parse(14); // passes
1249
1288
 
1250
1289
  Zod will test the input against each of the "options" in order and return the first value that validates successfully.
1251
1290
 
1252
- For convenience, you can also use the `.or` method:
1291
+ For convenience, you can also use the [`.or` method](#or):
1253
1292
 
1254
1293
  ```ts
1255
1294
  const stringOrNumber = z.string().or(z.number());
1256
1295
  ```
1257
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
+
1258
1313
  ## Discriminated unions
1259
1314
 
1260
1315
  A discriminated union is a union of object schemas that all share a particular key.
@@ -1267,7 +1322,7 @@ type MyUnion =
1267
1322
 
1268
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.
1269
1324
 
1270
- With the basic union method the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".
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".
1271
1326
 
1272
1327
  ```ts
1273
1328
  const myUnion = z.discriminatedUnion("status", [
@@ -1275,7 +1330,7 @@ const myUnion = z.discriminatedUnion("status", [
1275
1330
  z.object({ status: z.literal("failed"), error: z.instanceof(Error) }),
1276
1331
  ]);
1277
1332
 
1278
- myUnion.parse({ type: "success", data: "yippie ki yay" });
1333
+ myUnion.parse({ status: "success", data: "yippie ki yay" });
1279
1334
  ```
1280
1335
 
1281
1336
  ## Records
@@ -1416,55 +1471,67 @@ type Teacher = z.infer<typeof Teacher>;
1416
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".
1417
1472
 
1418
1473
  ```ts
1419
- interface Category {
1420
- name: string;
1474
+ const baseCategorySchema = z.object({
1475
+ name: z.string(),
1476
+ });
1477
+
1478
+ type Category = z.infer<typeof baseCategorySchema> & {
1421
1479
  subcategories: Category[];
1422
- }
1480
+ };
1423
1481
 
1424
- // cast to z.ZodType<Category>
1425
- const Category: z.ZodType<Category> = z.lazy(() =>
1426
- z.object({
1427
- name: z.string(),
1428
- subcategories: z.array(Category),
1429
- })
1430
- );
1482
+ const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
1483
+ subcategories: z.lazy(() => categorySchema.array()),
1484
+ });
1431
1485
 
1432
- Category.parse({
1486
+ categorySchema.parse({
1433
1487
  name: "People",
1434
1488
  subcategories: [
1435
1489
  {
1436
1490
  name: "Politicians",
1437
- subcategories: [{ name: "Presidents", subcategories: [] }],
1491
+ subcategories: [
1492
+ {
1493
+ name: "Presidents",
1494
+ subcategories: [],
1495
+ },
1496
+ ],
1438
1497
  },
1439
1498
  ],
1440
1499
  }); // passes
1441
1500
  ```
1442
1501
 
1443
- 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
1444
1505
 
1445
- <!-- 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>`
1446
1512
 
1447
1513
  ```ts
1448
- // define all the non-recursive stuff here
1449
- const BaseCategory = z.object({
1450
- name: z.string(),
1451
- tags: z.array(z.string()),
1452
- 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),
1453
1519
  });
1454
1520
 
1455
- // create an interface that extends the base schema
1456
- interface Category extends z.infer<typeof BaseCategory> {
1457
- subcategories: Category[];
1458
- }
1521
+ type Input = z.input<typeof baseSchema> & {
1522
+ children: Input[];
1523
+ };
1459
1524
 
1460
- // merge the base schema with
1461
- // a new Zod schema containing relations
1462
- const Category: z.ZodType<Category> = BaseCategory.merge(
1463
- z.object({
1464
- subcategories: z.lazy(() => z.array(Category)),
1465
- })
1466
- );
1467
- ``` -->
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.
1468
1535
 
1469
1536
  ### JSON type
1470
1537
 
@@ -1663,21 +1730,20 @@ Given any Zod schema, you can call its `.parse` method to check `data` is valid.
1663
1730
  const stringSchema = z.string();
1664
1731
 
1665
1732
  stringSchema.parse("fish"); // => returns "fish"
1666
- stringSchema.parse(12); // throws Error('Non-string type: number');
1733
+ stringSchema.parse(12); // throws error
1667
1734
  ```
1668
1735
 
1669
1736
  ### `.parseAsync`
1670
1737
 
1671
1738
  `.parseAsync(data:unknown): Promise<T>`
1672
1739
 
1673
- 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`.
1674
1741
 
1675
1742
  ```ts
1676
- const stringSchema1 = z.string().refine(async (val) => val.length < 20);
1677
- const value1 = await stringSchema.parseAsync("hello"); // => hello
1743
+ const stringSchema = z.string().refine(async (val) => val.length <= 8);
1678
1744
 
1679
- const stringSchema2 = z.string().refine(async (val) => val.length > 20);
1680
- const value2 = await stringSchema.parseAsync("hello"); // => throws
1745
+ await stringSchema.parseAsync("hello"); // => returns "hello"
1746
+ await stringSchema.parseAsync("hello world"); // => throws error
1681
1747
  ```
1682
1748
 
1683
1749
  ### `.safeParse`
@@ -1694,7 +1760,7 @@ stringSchema.safeParse("billie");
1694
1760
  // => { success: true; data: 'billie' }
1695
1761
  ```
1696
1762
 
1697
- 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:
1698
1764
 
1699
1765
  ```ts
1700
1766
  const result = stringSchema.safeParse("billie");
@@ -1762,7 +1828,7 @@ type RefineParams = {
1762
1828
  };
1763
1829
  ```
1764
1830
 
1765
- 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`.
1766
1832
 
1767
1833
  ```ts
1768
1834
  const longString = z.string().refine(
@@ -1873,7 +1939,7 @@ const Strings = z.array(z.string()).superRefine((val, ctx) => {
1873
1939
 
1874
1940
  You can add as many issues as you like. If `ctx.addIssue` is _not_ called during the execution of the function, validation passes.
1875
1941
 
1876
- 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).
1877
1943
 
1878
1944
  #### Abort early
1879
1945
 
@@ -1902,7 +1968,7 @@ const schema = z.number().superRefine((val, ctx) => {
1902
1968
 
1903
1969
  #### Type refinements
1904
1970
 
1905
- If you provide a [type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) to `.refine()` or `superRefine()`, the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:
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:
1906
1972
 
1907
1973
  ```ts
1908
1974
  const schema = z
@@ -1917,15 +1983,15 @@ const schema = z
1917
1983
  code: z.ZodIssueCode.custom, // customize your issue
1918
1984
  message: "object should exist",
1919
1985
  });
1920
- return false;
1921
1986
  }
1922
- return true;
1987
+
1988
+ return z.NEVER; // The return value is not used, but we need to return something to satisfy the typing
1923
1989
  })
1924
1990
  // here, TS knows that arg is not null
1925
1991
  .refine((arg) => arg.first === "bob", "`first` is not `bob`!");
1926
1992
  ```
1927
1993
 
1928
- > ⚠️ 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.
1929
1995
 
1930
1996
  ### `.transform`
1931
1997
 
@@ -1952,12 +2018,12 @@ emailToDomain.parse("colinhacks@example.com"); // => example.com
1952
2018
 
1953
2019
  #### Validating during transform
1954
2020
 
1955
- 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`.
1956
2022
 
1957
- 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.
1958
2024
 
1959
2025
  ```ts
1960
- const Strings = z.string().transform((val, ctx) => {
2026
+ const numberInString = z.string().transform((val, ctx) => {
1961
2027
  const parsed = parseInt(val);
1962
2028
  if (isNaN(parsed)) {
1963
2029
  ctx.addIssue({
@@ -2028,6 +2094,19 @@ Conceptually, this is how Zod processes default values:
2028
2094
  1. If the input is `undefined`, the default value is returned
2029
2095
  2. Otherwise, the data is parsed using the base schema
2030
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
+
2031
2110
  ### `.catch`
2032
2111
 
2033
2112
  Use `.catch()` to provide a "catch value" to be returned in the event of a parsing error.
@@ -2111,7 +2190,7 @@ z.promise(z.string());
2111
2190
 
2112
2191
  ### `.or`
2113
2192
 
2114
- A convenience method for union types.
2193
+ A convenience method for [union types](#unions).
2115
2194
 
2116
2195
  ```ts
2117
2196
  const stringOrNumber = z.string().or(z.number()); // string | number
@@ -2292,7 +2371,7 @@ if (!data.success) {
2292
2371
 
2293
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)
2294
2373
 
2295
- 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)
2296
2375
 
2297
2376
  ### Error formatting
2298
2377
 
@@ -2445,7 +2524,7 @@ This more declarative API makes schema definitions vastly more concise.
2445
2524
 
2446
2525
  [https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
2447
2526
 
2448
- 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.
2449
2528
 
2450
2529
  - Supports "pattern matching": computed properties that distribute over unions
2451
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;