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(() => ...)。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台