zod 3.14.0 → 3.14.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 +72 -10
- package/lib/benchmarks/index.js +2 -0
- package/lib/benchmarks/primitives.d.ts +5 -0
- package/lib/benchmarks/primitives.js +78 -0
- package/lib/benchmarks/string.js +11 -0
- package/lib/helpers/parseUtil.d.ts +6 -3
- package/lib/helpers/parseUtil.js +2 -2
- package/lib/index.mjs +174 -152
- package/lib/types.d.ts +6 -8
- package/lib/types.js +174 -150
- package/package.json +31 -38
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<h1 align="center">Zod</h1>
|
|
4
4
|
</p>
|
|
5
5
|
<p align="center">
|
|
6
|
+
<a href="https://github.com/edgedb/edgedb-js/actions"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Zod CI status" /></a>
|
|
6
7
|
<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>
|
|
7
8
|
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a>
|
|
8
9
|
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a>
|
|
9
10
|
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a>
|
|
10
|
-
<a href="./src/__tests__" rel="nofollow"><img src="./coverage.svg" alt="coverage"></a>
|
|
11
11
|
<a href="https://discord.gg/KaSRdyX2vc" rel="nofollow"><img src="https://img.shields.io/discord/893487829802418277?label=Discord&logo=discord&logoColor=white" alt="discord server"></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -94,8 +94,10 @@ These docs have been translated into [Chinese](./README_ZH.md).
|
|
|
94
94
|
- [.promise](#promise)
|
|
95
95
|
- [.or](#or)
|
|
96
96
|
- [.and](#and)
|
|
97
|
-
- [
|
|
98
|
-
- [
|
|
97
|
+
- [Guides and concepts](#guides-and-concepts)
|
|
98
|
+
- [Type inference](#type-inference)
|
|
99
|
+
- [Writing generic functions](#writing-generic-functions)
|
|
100
|
+
- [Error handling](#error-handling)
|
|
99
101
|
- [Comparison](#comparison)
|
|
100
102
|
- [Joi](#joi)
|
|
101
103
|
- [Yup](#yup)
|
|
@@ -241,6 +243,8 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
241
243
|
- [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod.
|
|
242
244
|
- [`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
|
|
243
245
|
- [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema.
|
|
246
|
+
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas
|
|
247
|
+
- [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs
|
|
244
248
|
|
|
245
249
|
### Form integrations
|
|
246
250
|
|
|
@@ -1687,7 +1691,9 @@ z.object({ name: z.string() }).and(z.object({ age: z.number() })); // { name: st
|
|
|
1687
1691
|
z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
|
1688
1692
|
```
|
|
1689
1693
|
|
|
1690
|
-
#
|
|
1694
|
+
# Guides and concepts
|
|
1695
|
+
|
|
1696
|
+
## Type inference
|
|
1691
1697
|
|
|
1692
1698
|
You can extract the TypeScript type of any schema with `z.infer<typeof mySchema>` .
|
|
1693
1699
|
|
|
@@ -1716,16 +1722,72 @@ type output = z.output<typeof stringToNumber>; // number
|
|
|
1716
1722
|
type inferred = z.infer<typeof stringToNumber>; // number
|
|
1717
1723
|
```
|
|
1718
1724
|
|
|
1719
|
-
|
|
1725
|
+
## Writing generic functions
|
|
1726
|
+
|
|
1727
|
+
When attempting to write a functions that accepts a Zod schemas as an input, it's common to try something like this:
|
|
1728
|
+
|
|
1729
|
+
```ts
|
|
1730
|
+
function makeSchemaOptional<T>(schema: z.ZodType<T>) {
|
|
1731
|
+
return schema.optional();
|
|
1732
|
+
}
|
|
1733
|
+
```
|
|
1734
|
+
|
|
1735
|
+
This approach has some issues. The `schema` variable in this function is typed as an instance of `ZodType`, which is an abstract class that all Zod schemas inherit from. This approach loses type information, namely _which subclass_ the input actually is.
|
|
1736
|
+
|
|
1737
|
+
```ts
|
|
1738
|
+
const arg = makeSchemaOptional(z.string());
|
|
1739
|
+
arg.unwrap();
|
|
1740
|
+
```
|
|
1741
|
+
|
|
1742
|
+
A better approach is for the generate parameter to refer to _the schema as a whole_.
|
|
1743
|
+
|
|
1744
|
+
```ts
|
|
1745
|
+
function makeSchemaOptional<T extends z.ZodTypeAny>(schema: T) {
|
|
1746
|
+
return schema.optional();
|
|
1747
|
+
}
|
|
1748
|
+
```
|
|
1749
|
+
|
|
1750
|
+
> `ZodTypeAny` is just a shorthand for `ZodType<any, any, any>`, a type that is broad enough to match any Zod schema.
|
|
1751
|
+
|
|
1752
|
+
As you can see, `schema` is now fully and properly typed.
|
|
1753
|
+
|
|
1754
|
+
```ts
|
|
1755
|
+
const arg = makeSchemaOptional(z.string());
|
|
1756
|
+
arg.unwrap(); // ZodString
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
### Restricting valid schemas
|
|
1760
|
+
|
|
1761
|
+
The `ZodType` class has three generic parameters.
|
|
1762
|
+
|
|
1763
|
+
```ts
|
|
1764
|
+
class ZodType<
|
|
1765
|
+
Output,
|
|
1766
|
+
Def extends ZodTypeDef = ZodTypeDef,
|
|
1767
|
+
Input = Output
|
|
1768
|
+
> { ... }
|
|
1769
|
+
```
|
|
1770
|
+
|
|
1771
|
+
By contraining these in your generic input, you can limit what schemas are allowable as inputs to your function:
|
|
1772
|
+
|
|
1773
|
+
```ts
|
|
1774
|
+
function makeSchemaOptional<T extends z.ZodType<string>>(schema: T) {
|
|
1775
|
+
return schema.optional();
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
makeSchemaOptional(z.string());
|
|
1779
|
+
// works fine
|
|
1780
|
+
|
|
1781
|
+
makeSchemaOptional(z.number());
|
|
1782
|
+
// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType<string, ZodTypeDef, string>'
|
|
1783
|
+
```
|
|
1784
|
+
|
|
1785
|
+
## Error handling
|
|
1720
1786
|
|
|
1721
1787
|
Zod provides a subclass of Error called `ZodError`. ZodErrors contain an `issues` array containing detailed information about the validation problems.
|
|
1722
1788
|
|
|
1723
1789
|
```ts
|
|
1724
|
-
const data = z
|
|
1725
|
-
.object({
|
|
1726
|
-
name: z.string(),
|
|
1727
|
-
})
|
|
1728
|
-
.safeParse({ name: 12 });
|
|
1790
|
+
const data = z.object({ name: z.string() }).safeParse({ name: 12 });
|
|
1729
1791
|
|
|
1730
1792
|
if (!data.success) {
|
|
1731
1793
|
data.error.issues;
|
package/lib/benchmarks/index.js
CHANGED
|
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const discriminatedUnion_1 = __importDefault(require("./discriminatedUnion"));
|
|
7
7
|
const object_1 = __importDefault(require("./object"));
|
|
8
|
+
const primitives_1 = __importDefault(require("./primitives"));
|
|
8
9
|
const realworld_1 = __importDefault(require("./realworld"));
|
|
9
10
|
const string_1 = __importDefault(require("./string"));
|
|
10
11
|
const union_1 = __importDefault(require("./union"));
|
|
11
12
|
for (const suite of [
|
|
12
13
|
...realworld_1.default.suites,
|
|
14
|
+
...primitives_1.default.suites,
|
|
13
15
|
...string_1.default.suites,
|
|
14
16
|
...object_1.default.suites,
|
|
15
17
|
...union_1.default.suites,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const benchmark_1 = __importDefault(require("benchmark"));
|
|
7
|
+
const index_1 = require("../index");
|
|
8
|
+
const enumSuite = new benchmark_1.default.Suite("z.enum");
|
|
9
|
+
const enumSchema = index_1.z.enum(["a", "b", "c"]);
|
|
10
|
+
enumSuite
|
|
11
|
+
.add("valid", () => {
|
|
12
|
+
enumSchema.parse("a");
|
|
13
|
+
})
|
|
14
|
+
.add("invalid", () => {
|
|
15
|
+
try {
|
|
16
|
+
enumSchema.parse("x");
|
|
17
|
+
}
|
|
18
|
+
catch (e) { }
|
|
19
|
+
})
|
|
20
|
+
.on("cycle", (e) => {
|
|
21
|
+
console.log(`z.enum: ${e.target}`);
|
|
22
|
+
});
|
|
23
|
+
const undefinedSuite = new benchmark_1.default.Suite("z.undefined");
|
|
24
|
+
const undefinedSchema = index_1.z.undefined();
|
|
25
|
+
undefinedSuite
|
|
26
|
+
.add("valid", () => {
|
|
27
|
+
undefinedSchema.parse(undefined);
|
|
28
|
+
})
|
|
29
|
+
.add("invalid", () => {
|
|
30
|
+
try {
|
|
31
|
+
undefinedSchema.parse(1);
|
|
32
|
+
}
|
|
33
|
+
catch (e) { }
|
|
34
|
+
})
|
|
35
|
+
.on("cycle", (e) => {
|
|
36
|
+
console.log(`z.undefined: ${e.target}`);
|
|
37
|
+
});
|
|
38
|
+
const literalSuite = new benchmark_1.default.Suite("z.literal");
|
|
39
|
+
const short = "short";
|
|
40
|
+
const bad = "bad";
|
|
41
|
+
const literalSchema = index_1.z.literal("short");
|
|
42
|
+
literalSuite
|
|
43
|
+
.add("valid", () => {
|
|
44
|
+
literalSchema.parse(short);
|
|
45
|
+
})
|
|
46
|
+
.add("invalid", () => {
|
|
47
|
+
try {
|
|
48
|
+
literalSchema.parse(bad);
|
|
49
|
+
}
|
|
50
|
+
catch (e) { }
|
|
51
|
+
})
|
|
52
|
+
.on("cycle", (e) => {
|
|
53
|
+
console.log(`z.literal: ${e.target}`);
|
|
54
|
+
});
|
|
55
|
+
const numberSuite = new benchmark_1.default.Suite("z.number");
|
|
56
|
+
const numberSchema = index_1.z.number().int();
|
|
57
|
+
numberSuite
|
|
58
|
+
.add("valid", () => {
|
|
59
|
+
numberSchema.parse(1);
|
|
60
|
+
})
|
|
61
|
+
.add("invalid type", () => {
|
|
62
|
+
try {
|
|
63
|
+
numberSchema.parse("bad");
|
|
64
|
+
}
|
|
65
|
+
catch (e) { }
|
|
66
|
+
})
|
|
67
|
+
.add("invalid number", () => {
|
|
68
|
+
try {
|
|
69
|
+
numberSchema.parse(0.5);
|
|
70
|
+
}
|
|
71
|
+
catch (e) { }
|
|
72
|
+
})
|
|
73
|
+
.on("cycle", (e) => {
|
|
74
|
+
console.log(`z.number: ${e.target}`);
|
|
75
|
+
});
|
|
76
|
+
exports.default = {
|
|
77
|
+
suites: [enumSuite, undefinedSuite, literalSuite, numberSuite],
|
|
78
|
+
};
|
package/lib/benchmarks/string.js
CHANGED
|
@@ -17,6 +17,8 @@ const manual = (str) => {
|
|
|
17
17
|
return str;
|
|
18
18
|
};
|
|
19
19
|
const stringSchema = index_1.z.string();
|
|
20
|
+
const optionalStringSchema = index_1.z.string().optional();
|
|
21
|
+
const optionalNullableStringSchema = index_1.z.string().optional().nullable();
|
|
20
22
|
suite
|
|
21
23
|
.add("empty string", () => {
|
|
22
24
|
stringSchema.parse(empty);
|
|
@@ -26,6 +28,15 @@ suite
|
|
|
26
28
|
})
|
|
27
29
|
.add("long string", () => {
|
|
28
30
|
stringSchema.parse(long);
|
|
31
|
+
})
|
|
32
|
+
.add("optional string", () => {
|
|
33
|
+
optionalStringSchema.parse(long);
|
|
34
|
+
})
|
|
35
|
+
.add("nullable string", () => {
|
|
36
|
+
optionalNullableStringSchema.parse(long);
|
|
37
|
+
})
|
|
38
|
+
.add("nullable (null) string", () => {
|
|
39
|
+
optionalNullableStringSchema.parse(null);
|
|
29
40
|
})
|
|
30
41
|
.add("invalid: null", () => {
|
|
31
42
|
try {
|
|
@@ -38,11 +38,14 @@ export declare type ParsePathComponent = string | number;
|
|
|
38
38
|
export declare type ParsePath = ParsePathComponent[];
|
|
39
39
|
export declare const EMPTY_PATH: ParsePath;
|
|
40
40
|
export interface ParseContext {
|
|
41
|
+
readonly common: {
|
|
42
|
+
readonly issues: ZodIssue[];
|
|
43
|
+
readonly contextualErrorMap?: ZodErrorMap;
|
|
44
|
+
readonly async: boolean;
|
|
45
|
+
readonly typeCache: Map<any, ZodParsedType> | undefined;
|
|
46
|
+
};
|
|
41
47
|
readonly path: ParsePath;
|
|
42
|
-
readonly issues: ZodIssue[];
|
|
43
48
|
readonly schemaErrorMap?: ZodErrorMap;
|
|
44
|
-
readonly contextualErrorMap?: ZodErrorMap;
|
|
45
|
-
readonly async: boolean;
|
|
46
49
|
readonly parent: ParseContext | null;
|
|
47
50
|
readonly data: any;
|
|
48
51
|
readonly parsedType: ZodParsedType;
|
package/lib/helpers/parseUtil.js
CHANGED
|
@@ -97,13 +97,13 @@ function addIssueToContext(ctx, issueData) {
|
|
|
97
97
|
data: ctx.data,
|
|
98
98
|
path: ctx.path,
|
|
99
99
|
errorMaps: [
|
|
100
|
-
ctx.contextualErrorMap,
|
|
100
|
+
ctx.common.contextualErrorMap,
|
|
101
101
|
ctx.schemaErrorMap,
|
|
102
102
|
ZodError_1.overrideErrorMap,
|
|
103
103
|
ZodError_1.defaultErrorMap, // then global default map
|
|
104
104
|
].filter((x) => !!x),
|
|
105
105
|
});
|
|
106
|
-
ctx.issues.push(issue);
|
|
106
|
+
ctx.common.issues.push(issue);
|
|
107
107
|
}
|
|
108
108
|
exports.addIssueToContext = addIssueToContext;
|
|
109
109
|
class ParseStatus {
|