Skip to content

Commit

Permalink
Merge branch 'master' into string-date-time
Browse files Browse the repository at this point in the history
  • Loading branch information
igalklebanov authored Feb 27, 2023
2 parents 14f395a + d6f0890 commit 986c54d
Show file tree
Hide file tree
Showing 19 changed files with 1,077 additions and 195 deletions.
32 changes: 16 additions & 16 deletions ERROR_HANDLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ _Every_ ZodIssue has these fields:

## ZodIssueCode

| code | additional fields |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ZodIssueCode.invalid_type | `expected: ZodParsedType` <br> `received: ZodParsedType` <br><br>Jump to [this section](#zodparsedtype) for a breakdown of the possible values of ZodParsedType. |
| ZodIssueCode.unrecognized_keys | `keys: string[]`<br>The list of unrecognized keys<br> |
| ZodIssueCode.invalid_union | `unionErrors: ZodError[]` <br> The errors thrown by each element of the union. |
| ZodIssueCode.invalid_enum_value | `options: string[]` <br> The set of acceptable string values for this enum. |
| ZodIssueCode.invalid_arguments | `argumentsError: ZodError` <br> This is a special error code only thrown by a wrapped function returned by `ZodFunction.implement()`. The `argumentsError` property is another ZodError containing the validation error details. |
| ZodIssueCode.invalid_return_type | `returnTypeError: ZodError` <br> This is a special error code only thrown by a wrapped function returned by `ZodFunction.implement()`. The `returnTypeError` property is another ZodError containing the validation error details. |
| ZodIssueCode.invalid_date | _no additional properties_ |
| ZodIssueCode.invalid_string | `validation: "url" \| "email" \| "uuid"`<br> Which built-in string validator failed |
| ZodIssueCode.too_small | `type: "string" \| "number" \| "array"` <br>The type of the data failing validation<br><br> `minimum: number` <br>The expected length/value.<br><br>`inclusive: boolean`<br>Whether the minimum is included in the range of acceptable values.<br> |
| ZodIssueCode.too_big | `type: "string" \| "number" \| "array"` <br>The type of the data failing validation<br><br> `maximum: number` <br>The expected length/value.<br><br>`inclusive: boolean`<br>Whether the maximum is included in the range of acceptable values.<br> |
| ZodIssueCode.not_multiple_of | `multipleOf: number` <br>The value the number should be a multiple of.<br> |
| ZodIssueCode.custom | `params: { [k: string]: any }` <br> This is the error code throw by refinements (unless you are using `superRefine` in which case it's possible to throw issues of any `ZodIssueCode`). You are able to pass in a `params` object here that is available in your custom error maps (see [ZodErrorMap](#Customizing-errors-with-ZodErrorMap) below for details on error maps) |
| code | additional fields |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ZodIssueCode.invalid_type | `expected: ZodParsedType` <br> `received: ZodParsedType` <br><br>Jump to [this section](#zodparsedtype) for a breakdown of the possible values of ZodParsedType. |
| ZodIssueCode.unrecognized_keys | `keys: string[]`<br>The list of unrecognized keys<br> |
| ZodIssueCode.invalid_union | `unionErrors: ZodError[]` <br> The errors thrown by each element of the union. |
| ZodIssueCode.invalid_enum_value | `options: string[]` <br> The set of acceptable string values for this enum. |
| ZodIssueCode.invalid_arguments | `argumentsError: ZodError` <br> This is a special error code only thrown by a wrapped function returned by `ZodFunction.implement()`. The `argumentsError` property is another ZodError containing the validation error details. |
| ZodIssueCode.invalid_return_type | `returnTypeError: ZodError` <br> This is a special error code only thrown by a wrapped function returned by `ZodFunction.implement()`. The `returnTypeError` property is another ZodError containing the validation error details. |
| ZodIssueCode.invalid_date | _no additional properties_ |
| ZodIssueCode.invalid_string | `validation: "url" \| "email" \| "uuid"`<br> Which built-in string validator failed |
| ZodIssueCode.too_small | `type: "string" \| "number" \| "array" \| "set" \| "date"` <br>The type of the data failing validation<br><br> `minimum: number` <br>The expected length/value.<br><br>`inclusive: boolean`<br>Whether the minimum is included in the range of acceptable values.<br><br>`exact: boolean`<br>Whether the size/length is constrained to be an exact value (used to produce more readable error messages).<br> |
| ZodIssueCode.too_big | `type: "string" \| "number" \| "array" \| "set" \| "date"` <br>The type of the data failing validation<br><br> `maximum: number` <br>The expected length/value.<br><br>`inclusive: boolean`<br>Whether the maximum is included in the range of acceptable values.<br><br>`exact: boolean`<br>Whether the size/length is constrained to be an exact value (used to produce more readable error messages).<br> |
| ZodIssueCode.not_multiple_of | `multipleOf: number` <br>The value the number should be a multiple of.<br> |
| ZodIssueCode.custom | `params: { [k: string]: any }` <br> This is the error code throw by refinements (unless you are using `superRefine` in which case it's possible to throw issues of any `ZodIssueCode`). You are able to pass in a `params` object here that is available in your custom error maps (see [ZodErrorMap](#Customizing-errors-with-ZodErrorMap) below for details on error maps) |

<!--
| ZodIssueCode.nonempty_array_is_empty | _no additional properties_ |
Expand Down Expand Up @@ -232,7 +232,7 @@ Let's look at a practical example of of customized error map:
```ts
import * as z from "zod";

const errorMap: z.ZodErrorMap = (error, ctx) => {
const customErrorMap: z.ZodErrorMap = (error, ctx) => {
/*
This is where you override the various error codes
*/
Expand All @@ -257,7 +257,7 @@ const errorMap: z.ZodErrorMap = (error, ctx) => {
return { message: ctx.defaultError };
};

z.string().parse(12, { errorMap });
z.string().parse(12, { errorMap: customErrorMap });

/* throws:
ZodError {
Expand Down
87 changes: 75 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://www.npmjs.com/package/zod">npm</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://deno.land/x/zod">deno</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://github.com/colinhacks/zod/issues/new">Issues</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://twitter.com/colinhacks">@colinhacks</a>
Expand Down Expand Up @@ -55,7 +57,10 @@
- [Coercion for primitives](#coercion-for-primitives)
- [Literals](#literals)
- [Strings](#strings)
- [Datetime](#datetime-validation)
- [IP](#ip-address-validation)
- [Numbers](#numbers)
- [BigInts](#bigints)
- [NaNs](#nans)
- [Booleans](#booleans)
- [Dates](#dates)
Expand Down Expand Up @@ -586,16 +591,20 @@ z.string().min(5);
z.string().length(5);
z.string().email();
z.string().url();
z.string().emoji();
z.string().uuid();
z.string().cuid();
z.string().cuid2();
z.string().regex(regex);
z.string().startsWith(string);
z.string().endsWith(string);
z.string().trim(); // trim whitespace
z.string().toLowerCase(); // toLowerCase
z.string().toUpperCase(); // toLowerCase
z.string().datetime(); // defaults to UTC, see below for options
z.string().date(); // ISO short date format.
z.string().time(); // time of day in 24-hour format, see below for options.
z.string().ip(); // defaults to IPv4 and IPv6, see below for options
```

> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions that can be used in conjunction with [Refinements](#refine).
Expand All @@ -617,12 +626,14 @@ z.string().max(5, { message: "Must be 5 or fewer characters long" });
z.string().length(5, { message: "Must be exactly 5 characters long" });
z.string().email({ message: "Invalid email address" });
z.string().url({ message: "Invalid url" });
z.string().emoji({ message: "Contains non-emoji characters" });
z.string().uuid({ message: "Invalid UUID" });
z.string().startsWith("https://", { message: "Must provide secure URL" });
z.string().endsWith(".com", { message: "Only .com domains allowed" });
z.string().datetime({ message: "Invalid datetime string! Must be UTC." });
z.string().date({ message: "Invalid date string!" });
z.string().time({ message: "Invalid time string!" });
z.string().ip({ message: "Invalid IP address" });
```

### Date, Time & Datetime validation
Expand Down Expand Up @@ -697,6 +708,31 @@ time.parse("00:00:00"); // fail
time.parse("00:00:00.123456"); // fail
```

### IP address validation

The `z.string().ip()` method by default validate IPv4 and IPv6.

```ts
const ip = z.string().ip();

ip.parse("192.168.1.1"); // pass
ip.parse("84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"); // pass
ip.parse("84d5:51a0:9114:1855:4cfa:f2d7:1f12:192.168.1.1"); // pass

ip.parse("256.1.1.1"); // fail
ip.parse("84d5:51a0:9114:gggg:4cfa:f2d7:1f12:7003"); // fail
```

You can additionally set the IP `version`.

```ts
const ipv4 = z.string().ip({ version: "v4" });
ipv4.parse("84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"); // fail

const ipv6 = z.string().ip({ version: "v6" });
ipv6.parse("192.168.1.1"); // fail
```

## Numbers

You can customize certain error messages when creating a number schema.
Expand Down Expand Up @@ -734,6 +770,24 @@ Optionally, you can pass in a second argument to provide a custom error message.
z.number().lte(5, { message: "this👏is👏too👏big" });
```

## BigInts

Zod includes a handful of bigint-specific validations.

```ts
z.bigint().gt(5n);
z.bigint().gte(5n); // alias `.min(5n)`
z.bigint().lt(5n);
z.bigint().lte(5n); // alias `.max(5n)`

z.bigint().positive(); // > 0n
z.bigint().nonnegative(); // >= 0n
z.bigint().negative(); // < 0n
z.bigint().nonpositive(); // <= 0n

z.bigint().multipleOf(5n); // Evenly divisible by 5n.
```

## NaNs

You can customize certain error messages when creating a nan schema.
Expand Down Expand Up @@ -1450,7 +1504,7 @@ type NumberSet = z.infer<typeof numberSet>;
// type NumberSet = Set<number>
```

Set schemas can be further contrainted with the following utility methods.
Set schemas can be further constrained with the following utility methods.

```ts
z.set(z.string()).nonempty(); // must contain at least one item
Expand Down Expand Up @@ -1755,6 +1809,12 @@ If you don't provide a validation function, Zod will allow any value. This can b
z.custom<{ arg: string }>(); // performs no validation
```

You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of [`.refine`](#refine).

```ts
z.custom<...>((val) => ..., "custom error message");
```

## Schema methods

All Zod schemas contain certain methods.
Expand Down Expand Up @@ -2159,14 +2219,17 @@ numberWithCatch.parse(5); // => 5
numberWithCatch.parse("tuna"); // => 42
```

Optionally, you can pass a function into `.catch` that will be re-executed whenever a default value needs to be generated:
Optionally, you can pass a function into `.catch` that will be re-executed whenever a default value needs to be generated. A `ctx` object containing the caught error will be passed into this function.

```ts
const numberWithRandomCatch = z.number().catch(Math.random);
const numberWithRandomCatch = z.number().catch((ctx) => {
ctx.error; // the caught ZodError
return Math.random();
});

numberWithRandomDefault.parse("sup"); // => 0.4413456736055323
numberWithRandomDefault.parse("sup"); // => 0.1871840107401901
numberWithRandomDefault.parse("sup"); // => 0.7223408162401552
numberWithRandomCatch.parse("sup"); // => 0.4413456736055323
numberWithRandomCatch.parse("sup"); // => 0.1871840107401901
numberWithRandomCatch.parse("sup"); // => 0.7223408162401552
```

Conceptually, this is how Zod processes "catch values":
Expand Down Expand Up @@ -2390,14 +2453,14 @@ makeSchemaOptional(z.number());
Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.

```ts
const data = z
const result = z
.object({
name: z.string(),
})
.safeParse({ name: 12 });

if (!data.success) {
data.error.issues;
if (!result.success) {
result.error.issues;
/* [
{
"code": "invalid_type",
Expand All @@ -2419,14 +2482,14 @@ Zod's error reporting emphasizes _completeness_ and _correctness_. If you are lo
You can use the `.format()` method to convert this error into a nested object.

```ts
const data = z
const result = z
.object({
name: z.string(),
})
.safeParse({ name: 12 });

if (!data.success) {
const formatted = data.error.format();
if (!result.success) {
const formatted = result.error.format();
/* {
name: { _errors: [ 'Expected string, received number' ] }
} */
Expand Down
Loading

0 comments on commit 986c54d

Please sign in to comment.