Zod 是一个专为 TypeScript 设计的“模式声明和数据验证”库。它能帮你定义数据结构规则(Schema),并在程序运行时检查数据是否符合这些规则,保证数据安全且类型正确。最棒的是,你只需写一遍规则,Zod 就会帮你自动生成对应的 TypeScript 类型,实现编译时和运行时的双重保护。
1. Zod 是什么?
- 模式声明(Schema) :用来描述数据的形状和类型,比如字符串、数字、对象结构等。
- 运行时验证:Zod 会检查实际数据是否符合你定义的模式。
- 自动类型推断:通过
z.infer
,Zod 自动生成对应的 TypeScript 类型,避免重复写类型声明。 - 零依赖且体积小:压缩后只有约8KB,适合浏览器和 Node.js 环境。
2. Zod 的核心功能
2.1 基本类型验证
Zod 支持字符串、数字、布尔值、日期等多种基本类型验证。
import { z } from "zod";
const stringSchema = z.string();
stringSchema.parse("hello"); // 通过验证,返回 "hello"
stringSchema.parse(123); // 抛出错误,类型不匹配
const numberSchema = z.number();
numberSchema.parse(42); // 通过验证
numberSchema.parse("42"); // 抛出错误
2.2 对象结构验证
定义对象的字段和类型,支持设置字段规则(如最小长度、最小值等)。
const userSchema = z.object({
name: z.string().min(3, "名字至少3个字符"),
age: z.number().min(18, "年龄必须至少18岁"),
});
const validUser = { name: "小明", age: 20 };
userSchema.parse(validUser); // 通过验证
const invalidUser = { name: "小", age: 16 };
userSchema.parse(invalidUser); // 抛出错误,name和age不符合规则
2.3 数组验证
验证数组中每个元素的类型。
const numberArray = z.array(z.number());
numberArray.parse([1, 2, 3]); // 通过验证
numberArray.parse([1, "2", 3]); // 抛出错误,数组中有字符串
2.4 联合类型和枚举验证
验证数据是否属于多个类型之一,或是否是枚举中的一个值。
const roleSchema = z.enum(["Admin", "User", "Guest"]);
roleSchema.parse("Admin"); // 通过验证
roleSchema.parse("SuperAdmin"); // 抛出错误
// 联合类型示例
const unionSchema = z.union([z.string(), z.number()]);
unionSchema.parse("hello"); // 通过
unionSchema.parse(123); // 通过
unionSchema.parse(true); // 抛出错误
2.5 自定义验证
使用 .refine()
或 .superRefine()
方法添加复杂的自定义规则。
const phoneSchema = z.object({
phone: z.string(),
confirmPhone: z.string(),
}).refine(data => data.phone === data.confirmPhone, {
message: "手机号和确认手机号必须一致",
});
phoneSchema.parse({ phone: "1234567890", confirmPhone: "1234567890" }); // 通过
phoneSchema.parse({ phone: "123", confirmPhone: "456" }); // 抛出错误
2.6 安全解析 .safeParse()
避免抛异常,返回验证结果对象,方便统一处理错误。
const result = z.string().safeParse(123);
if (!result.success) {
console.log(result.error.errors); // 打印详细错误信息
}
3. Zod 的使用场景举例
3.1 API 请求数据验证
确保前端发送到后端的数据格式正确,避免业务逻辑错误。
const requestSchema = z.object({
id: z.string(),
limit: z.number().optional(),
});
const requestData = { id: "abc123", limit: 10 };
requestSchema.parse(requestData); // 通过验证
3.2 表单数据验证
前端或后端验证用户输入,保证数据安全和用户体验。
const formSchema = z.object({
username: z.string().min(1, "用户名不能为空"),
email: z.string().email("邮箱格式不正确"),
});
try {
formSchema.parse({ username: "张三", email: "not-an-email" });
} catch (e) {
console.error(e.errors); // 输出邮箱格式错误信息
}
3.3 环境变量验证
启动时验证环境变量,避免配置错误导致程序异常。
const envSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
PORT: z.string().transform(val => parseInt(val, 10)),
});
const env = envSchema.parse(process.env);
console.log(env.PORT); // 确保 PORT 是数字类型
4. Zod 解决了哪些问题?
- 运行时类型缺失:TypeScript 只能编译时检查,Zod 补充运行时验证,保证数据安全。
- 减少重复声明:类型和验证规则写一处,自动推断类型,避免不一致。
- 简化复杂数据校验:链式调用轻松定义复杂嵌套结构。
- 统一错误处理:
.safeParse()
提供统一接口,方便捕获和处理错误。
5. 进阶示例:完整用户注册验证
import { z } from "zod";
const userSchema = z.object({
username: z.string().min(3, "用户名至少3个字符"),
password: z.string().min(6, "密码至少6位"),
email: z.string().email("无效的邮箱格式"),
birthDate: z.date().max(new Date(), "生日不能晚于今天"),
role: z.enum(["Admin", "User", "Guest"]),
});
type User = z.infer<typeof userSchema>;
const userInput = {
username: "张三",
password: "123456",
email: "zhangsan@example.com",
birthDate: new Date("1990-01-01"),
role: "User",
};
try {
const user: User = userSchema.parse(userInput);
console.log("验证通过,用户数据:", user);
} catch (e) {
console.error("验证失败:", e.errors);
}
6. 总结
Zod 是 TypeScript 项目中非常实用的工具,帮助你:
- 简单快速地定义数据结构和验证规则
- 自动推断类型,减少重复代码
- 运行时保证数据安全,避免异常和错误
- 支持丰富的类型和自定义验证,满足各种复杂场景
无论是前端表单、后端 API,还是环境配置,Zod 都能让你的代码更健壮、更易维护。
通过以上介绍和示例,你可以快速上手 Zod,提升你的 TypeScript 开发体验和代码质量。