Zod 完全指南:TypeScript 校验的事实标准
Zod 用声明式 Schema 同时获得运行时校验与 TypeScript 类型。本文讲解 Schema 定义、错误定制、错误映射、类型推导与框架集成。
Zod 的核心循环:z.object({...}) 定义 Schema → schema.parse(data) 校验(不符抛错)→ z.infer<typeof schema> 得到 TS 类型。一份定义三重收益:运行时校验、编译期类型、自动补全——全栈 TS 的基础设施。
快速上手
npm install zod
import { z } from 'zod';
const UserSchema = z.object({
name: z.string().min(2, '姓名至少 2 字'),
email: z.string().email('邮箱格式错误'),
age: z.number().int().min(18).optional(),
role: z.enum(['admin', 'user']).default('user'),
tags: z.array(z.string()).max(5),
});
type User = z.infer<typeof UserSchema>; // 类型自动推导
const user = UserSchema.parse(data); // 不符抛 ZodError,符合返回类型化数据
校验定制
z.string()
.regex(/^1[3-9]\d{9}$/, '手机号格式错误')
.transform(v => v.trim()); // 校验后转换
z.object({ password: z.string(), confirm: z.string() })
.refine(d => d.password === d.confirm, {
message: '两次密码不一致',
path: ['confirm'], // 错误挂到具体字段
});
z.string().superRefine(async (val, ctx) => { // 异步校验
if (await exists(val)) ctx.addIssue({ code: 'custom', message: '已存在' });
});
错误处理与映射
const result = UserSchema.safeParse(data);
if (!result.success) {
const fieldErrors = result.error.flatten().fieldErrors;
// { email: ['邮箱格式错误'], ... } —— 直接喂表单
}
全局错误映射(error map)统一中文化/业务化所有消息。
框架集成
- React Hook Form:
zodResolver(UserSchema)——表单校验即 Schema; - tRPC:procedure 的 input 直接放 Zod Schema——输入类型与校验一体;
- Next.js Server Actions:入参先 parse 再处理——边界安全标准姿势;
- 环境变量:启动时 parse process.env——配置错误启动即报。
常见问题(FAQ)
Q:parse 和 safeParse 怎么分工?
信任边界的入口(API 请求、外部数据)用 safeParse 显式处理;内部已校验数据用 parse(失败即编程错误)。
Q:Zod 4 的变化?
性能大幅提升、API 精简(z.email() 等新写法)、错误系统改进——新项目直接用最新版。
Q:递归 Schema(树结构)怎么写?
z.lazy() 包裹递归引用 + 显式类型标注:const Category: z.ZodType<Category> = z.lazy(() => ...)。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。