Zod
官方文档:Zod
官方GitHub:Zod
Zod
是一个以 TypeScript
为首的模式声明和验证库。我使用术语 "模式 "来广义地指任何数据类型,从简单的 字符串
到复杂的嵌套对象。
安装
bash
npm install zod
1
基本用法
schema.parse
:同步解析
schema.safeParse
:同步安全解析,不会抛出错误
schema.parseAsync
:异步解析
schema.safeParseAsync
:异步安全解析,不会抛出错误
typescript
import {z} from 'zod'
// 创建一个字符串模式
const schema = z.string()
// 解析
console.log(schema.parse('Hi')) // => Hi
console.log(schema.parse(1)) // error
// 安全解析,不会抛出错误
console.log(schema.safeParse('Hi')) // => { success: true, data: 'Hi' }
console.log(schema.safeParse(1)) // => { success: false, error: [Getter] }
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
typescript
import {z} from 'zod'
// 创建一个字符串模式
const schema = z.string()
// 解析
schema.parseAsync('Hi')
.then(value => console.log(value))
.catch(reason => console.dir(reason))
// 安全解析
schema.safeParseAsync(1)
.then(value => console.log(value))
// 安全结果返回的不是正确就是错误,所以无需捕捉错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
提取推断类型
zod.infer
typescript
import {z} from 'zod'
const userSchema = z.object({
name: z.string(),
age: z.number()
})
type User = z.infer<typeof userSchema>
const user: User = {
name: '张三',
age: 12
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
定义模式
原始值
typescript
import { z } from "zod";
// 原始值类型
z.string();
z.number();
z.bigint();
z.boolean();
z.date();
z.symbol();
// 空类型
z.undefined();
z.null();
z.void(); // 接受 undefined
// 任意类型
// 允许任意类型的值
z.any();
z.unknown();
// never 类型
// 不允许值类型存在
z.never();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
String
更多
查看 validatorjs,了解更多字符串验证函数
typescript
z.string().max(5); // 最大长度5
z.string().min(5); // 最小长度5
z.string().length(5); // 长度5
z.string().email(); // 邮箱
z.string().url(); // 链接
z.string().uuid(); // uuid
z.string().regex(regex); // 正则
z.string().startsWith(string); // 以字串开始
z.string().endsWith(string); // 以字串结束
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
自定义错误信息
可以传入第二个参数,来提供自定义错误信息
javascript
z.string().max(5, {message:'长度最大为 5'});
z.string().min(5, {message:'长度最小为 5'});
z.string().length(5, {message:'长度必须为 5'});
z.string().email({message:'邮箱格式不正确'});
1
2
3
4
2
3
4
Number
typescript
z.number().gt(5); // > 5
z.number().gte(5); // >= 5
z.number().lt(5); // < 5
z.number().lte(5); // <= 5
z.number().int(); // 值必须是一个整数
z.number().positive(); // > 0
z.number().nonnegative(); // >= 0
z.number().negative(); // < 0
z.number().nonpositive(); // <= 0
z.number().multipleOf(5); // x % 5 === 0
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
自定义错误信息
可以传入第二个参数,来提供自定义错误信息
typescript
z.number().gt(5, {message:'值必须 > 5'});
z.number().gte(5, {message:'值必须 >= 5'});
1
2
2
Date
typescript
z.date().safeParse(new Date()); // success: true
z.date({
required_error: "值不可为空",
invalid_type_error: "这不是一个有效的s",
});
z.date().min(new Date("1900-01-01"), { message: "Too old" });
z.date().max(new Date(), { message: "Too young!" });
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Object
typescript
import {string, z} from 'zod'
const userSchema = z.object({
name: z.string().optional(),
age: z.number()
})
console.log(userSchema.parse({'age': 15})) // 通过
console.log(userSchema.parse({name: '张三', age: 15})) // 通过
console.log(userSchema.parse({name: '张三'})) // 不通过
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Array
typescript
import {string, z} from 'zod'
const stringArraySchema = z.array(z.string())
// 提取推断类型
type ArraySchema = z.infer<typeof stringArraySchema> // string[]
// 解析
console.log(stringArraySchema.parse(['a','b'])) // 通过
console.log(stringArraySchema.parse([])) // 通过
console.log(stringArraySchema.parse([1,2])) // 不通过
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
不可为空数组 .nonempty
typescript
import {string, z} from 'zod'
const stringArraySchema = z.array(z.string()).nonempty()
// 提取推断类型
type ArraySchema = z.infer<typeof stringArraySchema> // string[]
// 解析
console.log(stringArraySchema.parse(['a','b'])) // 通过
console.log(stringArraySchema.parse([])) // 不通过
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
长度约束 length/min/max
typescript
array(z.string()).min(5); // 必须包含5个或更多元素
array(z.string()).max(5); // 必须包含5个或更少元素
array(z.string()).length(5); // 必须正好包含5个元素
1
2
3
2
3
可选
.optional
typescript
const schema = z.string().optional()
const userSchema = z.object({
name:z.string().optional() // 相当于 name? : string
})
1
2
3
4
5
2
3
4
5
null/undefined
.nullable
typescript
const schema = z.string().nullable()
const userSchema = z.object({
name:z.string().nullable() // 相当于 name : string | null | undefined
})
1
2
3
4
5
2
3
4
5
高级使用
typescript
const schema = z.nullable(z.boolean()) // true | false | null
1
自定类型
.instanceof()
typescript
// 例如: mongodb 的 ObjectId 类型
z.instanceof(ObjectId)
1
2
2
联合类型
.or()
typescript
import {z} from 'zod'
const schema = z.string().or(z.number()).or(z.boolean())
// schema : string | number | boolean
1
2
3
4
2
3
4
枚举
.nativeEnum
同样可以通过 zod.infer(type schema)
来提取推断类型
typescript
// 提取推断类型
type GenderEnum = z.infer<typeof genderSchema>
1
2
2
字符串枚举
typescript
import {z} from 'zod'
// 创建枚举
enum Gender {
boy = '男',
girl = '女',
}
// 定义 schema
const genderSchema = z.nativeEnum(Gender)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
typescript
genderSchema.parse(Gender.boy); // 通过
genderSchema.parse(Gender.girl); // 通过
genderSchema.parse('男'); // 通过
genderSchema.parse('女'); // 通过
genderSchema.parse('其他'); // 不通过
1
2
3
4
5
2
3
4
5
数字枚举
typescript
import {z} from 'zod'
// 创建枚举
enum Gender {
Boy,
Girl,
}
// 定义 schema
const genderSchema = z.nativeEnum(Gender)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
typescript
genderSchema.parse(Gender.Boy) // 通过
genderSchema.parse('Girl') // 不通过
genderSchema.parse(0) // 通过
genderSchema.parse(1) // 通过
genderSchema.parse(2) // 不通过
1
2
3
4
5
2
3
4
5
常量枚举
typescript
import {z} from 'zod'
// 创建枚举
const Gender = {
Boy: '男',
Girl: '女',
} as const;
// 定义 schema
const genderSchema = z.nativeEnum(Gender)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
typescript
genderSchema.parse(Gender.Boy) // 通过
genderSchema.parse('Girl') // 不通过
genderSchema.parse(0) // 不通过
genderSchema.parse('男') // 通过
genderSchema.parse('女') // 通过
1
2
3
4
5
2
3
4
5
错误处理
相关文档:zod_Error
可以使用以下简单的错误处理,更详细的请查看 错误处理 文档
typescript
z.string().max(5, {message:'长度最大为 5'});
z.string().min(5, {message:'长度最小为 5'});
z.string().length(5, {message:'长度必须为 5'});
z.string().email({message:'邮箱格式不正确'});
1
2
3
4
2
3
4