Zod
TypeScript-first 的 Schema 声明式校验库——以 TypeScript 类型推导为核心,在 tRPC 和 Next.js 生态中广泛使用。
Zod 是 TypeScript-first 的 Schema 校验库,定义一次 Schema 即可同时获得运行时校验和静态类型推导,v4 性能提升 14 倍,在 tRPC 和 Next.js 生态中不可替代,npm 周下载量超 1 亿次。
Zod
TypeScript-first 的 Schema 声明式校验库——以 TypeScript 类型推导为核心,在 tRPC 和 Next.js 生态中广泛使用。
技术简介说明
Zod 是由 Colin McDonnell 于 2020 年创建的 TypeScript-first Schema 声明与校验库。它的核心理念是「定义一次 Schema,同时获得运行时校验和静态类型推导」——开发者用 Zod 的链式 API 定义数据结构,TypeScript 编译器自动推导出对应的类型,运行时则通过 .parse() 方法对数据进行校验。这种「单一数据源」的设计消除了运行时校验与编译时类型之间的不一致问题,成为 TypeScript 生态中最受欢迎的数据校验方案。
Zod 在 tRPC 生态中扮演着不可替代的角色——tRPC 的输入校验完全依赖 Zod Schema,实现了从前端到后端的端到端类型安全。在 Next.js 生态中,Zod 同样被广泛用于 Server Actions 校验、API 路由校验和表单验证(配合 React Hook Form 的 zodResolver)。2025 年发布的 Zod v4 是一次里程碑式的重写,性能提升 14 倍,包体积缩小 57%,并引入了内置 JSON Schema 转换、@zod/mini 轻量变体等重要特性。
截至 2026 年,Zod 在 npm 上的周下载量超过 1 亿次,GitHub Stars 超过 43K,是 TypeScript 生态中使用最广泛的 Schema 校验库,深刻影响了 tRPC、Next.js、Fastify 等框架的数据校验实践。
基本信息
- 官网:https://zod.dev
- GitHub:https://github.com/colinhacks/zod
- License:MIT
- 最新版本:v4.4.0(2026 年)
- 主要维护者/公司:Colin McDonnell
- GitHub Stars:约 43,000+
- npm 周下载量:约 1 亿+(截至 2026 年)
- 贡献者:约 470+
快速上手
安装
# npm
npm install zod
# pnpm
pnpm add zod
# yarn
yarn add zod
# Deno(使用 npm 兼容层)
import { z } from "npm:zod"
# Bun
bun add zod基础配置
Zod 是零配置库,安装后直接使用,无需额外配置文件。
import { z } from "zod"
// 如果使用 Zod v4 且想渐进迁移,可通过子路径导入
import { z as z4 } from "zod/v4"最小示例
import { z } from "zod"
// 定义 Schema
const UserSchema = z.object({
username: z.string().min(3).max(20),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
})
// 推导 TypeScript 类型
type User = z.infer<typeof UserSchema>
// { username: string; email: string; age?: number | undefined }
// 运行时校验
const result = UserSchema.safeParse({
username: "john_doe",
email: "[email protected]",
age: 25,
})
if (result.success) {
console.log(result.data) // 类型安全的数据
} else {
console.log(result.error) // ZodError,包含详细的错误信息
}核心概念与架构
Schema 即类型
Zod 最核心的设计是「Schema 即类型」——每个 Zod Schema 同时是:
- 运行时校验器:通过
.parse()/.safeParse()在运行时校验数据 - TypeScript 类型生成器:通过
z.infer<typeof Schema>推导出对应的 TypeScript 类型
const StringSchema = z.string()
type StringType = z.infer<typeof StringSchema> // string
const ObjectSchema = z.object({
name: z.string(),
tags: z.array(z.string()),
})
type ObjectType = z.infer<typeof ObjectSchema>
// { name: string; tags: string[] }链式 API
Zod 的每个 Schema 类型都提供链式方法来添加约束:
z.string()
.min(1, "不能为空")
.max(100, "最多 100 个字符")
.email("邮箱格式不正确")
.optional()
.nullable()
.default("")解析模式
Zod 提供三种解析模式:
.parse():校验成功返回数据,失败抛出ZodError.safeParse():返回{ success: true, data }或{ success: false, error }.parseAsync()/.safeParseAsync():异步版本,支持异步 Schema(如.refine()返回 Promise)
错误处理
import { z } from "zod"
try {
z.string().parse(123)
} catch (e) {
if (e instanceof z.ZodError) {
console.log(e.errors)
// [{ code: "invalid_type", expected: "string", received: "number", path: [], message: "Expected string, received number" }]
}
}v4 架构改进
Zod v4 对内部架构进行了全面重写:
- 共享核心包:
zod/v4/core包含 Zod 和@zod/mini共享的核心逻辑 - Tree-shakable 设计:v4 的模块结构更利于 Tree-shaking,未使用的 Schema 类型不会被打包
- tsc 性能优化:减少了 TypeScript 编译器的类型推导负担,显著改善大型项目的
tsc编译速度 - 惰性绑定方法:减少内存使用,Schema 实例的方法不再在创建时绑定
核心特性
- TypeScript 类型推导:从 Schema 自动推导出精确的 TypeScript 类型,消除运行时与编译时的不一致
- 丰富的内置类型:string、number、boolean、date、bigint、symbol、undefined、null、void、any、unknown、never、array、tuple、object、union、intersection、enum、nativeEnum、literal、record、map、set、lazy、promise、effect 等
- 链式约束 API:
.min()、.max()、.email()、.url()、.uuid()、.regex()、.includes()、.startsWith()、.endsWith()等数十种约束方法 - 自定义校验(refine / superRefine):支持跨字段校验、异步校验、复杂业务规则
- Schema 转换(transform):在解析过程中对数据进行转换,如字符串转数字、格式化日期等
- 默认值(default)与可选(optional / nullable / nullish):灵活处理缺失值
- 管道(pipe):将多个 Schema 串联,前一级的输出作为后一级的输入
- 内置 JSON Schema 转换(v4):通过
z.toJSONSchema()原生生成 JSON Schema,用于 API 文档和 OpenAPI 规范 @zod/mini(v4):轻量变体,提供精简 API 和更小的包体积,适合对包大小敏感的场景- 全局元数据注册(v4):通过
z.globalRegistry存储强类型元数据,与 JSON Schema 生成联动 - 文件类型支持(v4):新增
z.file()类型,支持文件类型、大小校验 - 错误消息自定义:每个约束都支持自定义错误消息,支持国际化
生态图
核心生态
| 包名 / 工具 | 说明 |
|---|---|
zod | 核心库(主入口 zod,v4 子路径 zod/v4) |
@zod/mini | 轻量变体,Tree-shakable API |
zod/v4/core | Zod 和 Mini 共享的核心包 |
表单集成
| 工具 | 说明 |
|---|---|
react-hook-form + @hookform/resolvers/zod | React 表单方案,通过 zodResolver 集成 |
@vee-validate/zod | Vue 表单方案 VeeValidate 的 Zod 集成 |
@vee-validate/zod + FormKit | FormKit 可与 Zod 结合使用 |
formsnap | Svelte 表单库,深度集成 Zod |
后端 / API 集成
| 工具 | 说明 |
|---|---|
tRPC | 端到端类型安全 RPC 框架,输入校验完全基于 Zod |
@hono/zod-openapi | Hono 框架的 OpenAPI 集成 |
fastify-type-provider-zod | Fastify 的 Zod 类型提供者 |
drizzle-zod | 从 Drizzle ORM Schema 自动生成 Zod Schema |
prisma-zod / prisma-zod-generator | 从 Prisma Schema 生成 Zod Schema |
zod-prisma-types | Prisma + Zod 类型生成 |
JSON Schema / OpenAPI
| 工具 | 说明 |
|---|---|
zod(内置 v4) | v4 内置 z.toJSONSchema() 方法 |
zod-to-json-schema | 第三方转换库(v4 内置后已不再积极维护) |
zod-openapi | Zod Schema → OpenAPI 3.x 规范 |
验证扩展
| 工具 | 说明 |
|---|---|
zod-validation-error | 将 ZodError 格式化为人类可读消息 |
@standard-schema/utils | 标准 Schema 接口工具 |
zod-i18n-map | Zod 错误消息国际化 |
关键依赖关系
- TypeScript 5.0+:Zod 依赖 TypeScript 的类型系统特性
- tRPC:tRPC v10+ 将 Zod 作为默认(唯一推荐)输入校验库
- Next.js:Next.js App Router + Server Actions 场景中,Zod 是事实上的标准校验方案
适用场景
- tRPC 项目:tRPC 的输入校验完全依赖 Zod,使用 tRPC 即意味着使用 Zod
- Next.js Server Actions:在 Server Actions 中校验客户端提交的数据,Zod 是最主流的选择
- API 输入校验:Express / Fastify / Hono 等后端框架中校验请求体、查询参数、路由参数
- 前后端共享类型:通过
z.infer从 Schema 推导类型,在 Monorepo 中实现前后端类型共享 - 表单校验:配合 React Hook Form、VeeValidate 等表单库,实现客户端表单校验
- 配置文件校验:校验环境变量、配置文件、CLI 参数等结构化数据
- 数据库 Schema 映射:通过 drizzle-zod、prisma-zod 等工具从数据库 Schema 自动生成 Zod Schema,实现类型安全的数据层
- AI / LLM 输出校验:校验大语言模型返回的结构化数据(JSON),确保符合预期 Schema
开发与工程化
开发流程
# 克隆仓库
git clone https://github.com/colinhacks/zod.git
cd zod
# 安装依赖
pnpm install
# 运行测试
pnpm test
# 类型检查
pnpm typecheck
# 构建
pnpm build自定义 Schema 扩展
import { z } from "zod"
// 扩展自定义方法
const phoneSchema = z.string().refine(
(val) => /^1[3-9]\d{9}$/.test(val),
{ message: "请输入有效的手机号码" }
)
// 复用自定义 Schema
const contactSchema = z.object({
name: z.string(),
phone: phoneSchema,
email: z.string().email(),
})工程化最佳实践
- Schema 集中管理:将 Schema 定义集中在
schemas/或validators/目录,便于复用和维护 - Schema 与路由/处理器分离:在 API 层,Schema 定义和路由处理逻辑分离,Schema 作为独立模块
- 错误消息统一:创建错误消息工厂函数,统一管理错误消息格式
- 环境变量校验:使用 Zod 校验
.env文件,在应用启动时失败快速
// env.ts
import { z } from "zod"
const envSchema = z.object({
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().default(3000),
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
})
export const env = envSchema.parse(process.env)
// env.DATABASE_URL 类型为 string,env.PORT 类型为 numberCI/CD 集成
- 类型检查:
pnpm typecheck确保 Schema 定义和z.infer类型推导正确 - 单元测试:对关键 Schema 编写测试,覆盖边界条件和错误路径
- Contract Testing:在 Monorepo 中,用 Zod Schema 作为前后端契约,CI 中验证两端的一致性
性能与安全
性能特点(v4)
Zod v4 在性能方面进行了重大优化:
- 字符串解析:比 v3 快约 14 倍
- 数组解析:比 v3 快约 7 倍
- 整体性能:约 3-6 倍的整体性能提升
- 包体积:核心包缩小约 57%
- tsc 编译:TypeScript 编译器性能显著改善,减少大型项目的类型检查时间
- 内存使用:通过惰性绑定方法减少内存占用
⚠️ 注意:在某些特定场景(如 UI 密集型应用中的复杂嵌套 Schema)下,有社区报告指出 v4 可能比 v3 慢。建议根据实际项目做性能基准测试。
性能优化建议
- 使用
safeParse而非parse:避免异常捕获的开销 - 避免过度嵌套:深层嵌套的 object + union + tuple 会增加解析和类型推导成本
- 懒加载(lazy):对于大型递归 Schema,使用
z.lazy()避免启动时的初始化开销 - 选择
@zod/mini:如果不需要完整的 Zod API,@zod/mini提供更小的包体积 - 避免在热路径中使用
.refine():自定义 refine 函数无法被优化,对于简单约束优先使用内置方法
安全注意事项
- Zod 不能替代服务端验证:客户端 Zod 校验提升 UX,但服务端必须重新校验所有数据
- 输入消毒(Sanitization):Zod 校验数据结构但不自动消毒内容——需要额外的
z.string().transform()或专用库处理 XSS - 原型污染防护:Zod 的
z.object()使用Object.create(null)创建解析结果,但自定义.transform()中需要注意 - 大输入限制:对于超大 JSON 输入,注意设置解析大小限制,避免 DoS 攻击
- 依赖安全:Zod 本身零依赖,但注意
zod-to-json-schema等第三方包的安全更新
技术对比
| 特性 | Zod v4 | Yup | Valibot | Joi | ArkType |
|---|---|---|---|---|---|
| TypeScript 优先 | ✅ 核心设计 | ❌ 类型需额外处理 | ✅ 类型推导 | ❌ 需 @types | ✅ 类型推导 |
| 运行时校验 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 类型推导 | ✅ z.infer | 需 yup.InferType | ✅ InferInput | ❌ | ✅ infer<> |
| 包体积 | 中等(~57KB min+gzip) | 中等(~30KB) | 小(~8KB) | 大(~90KB) | 中等 |
| 零依赖 | ✅ | ✅ | ✅ | ❌ | ✅ |
| 异步校验 | ✅ | ✅ | ✅ | ✅ | ✅ |
| JSON Schema | ✅ 内置(v4) | ❌ | ❌ | ❌ | ❌ |
| 内置类型丰富度 | 非常丰富 | 中等 | 丰富 | 丰富 | 丰富 |
| 链式 API | ✅ | ✅ | ✅ 管道式 | ✅ | ✅ |
| 错误消息自定义 | ✅ 精细 | ✅ | ✅ | ✅ | ✅ |
| 社区生态 | 最大(tRPC / Next.js) | 大(Formik 默认) | 增长中 | 大(Express) | 增长中 |
| 性能 | 快(v4 优化) | 中等 | 快 | 慢 | 快 |
| 浏览器支持 | 现代浏览器 | 现代浏览器 | 现代浏览器 | 现代浏览器 | 现代浏览器 |
选型建议
- 选 Zod:使用 TypeScript、tRPC、Next.js,需要类型推导和运行时校验统一
- 选 Yup:使用 Formik 的项目,Yup 是 Formik 的默认校验方案
- 选 Valibot:对包大小极度敏感的项目,Valibot 的 Tree-shakable 设计使其可以只打包使用的模块
- 选 Joi:使用 Express / Hapi 的项目,Joi 在这些生态中有深厚积累
- 选 ArkType:追求极致类型推导精度,ArkType 的 TypeScript 类型系统利用更深入
最佳实践
1. 前后端共享 Schema(Monorepo)
// packages/shared/schemas/user.ts
import { z } from "zod"
export const createUserSchema = z.object({
username: z.string().min(3).max(20),
email: z.string().email(),
role: z.enum(["admin", "user"]),
})
export type CreateUserInput = z.infer<typeof createUserSchema>// apps/api/routes/users.ts
import { createUserSchema } from "@shared/schemas/user"
app.post("/users", (req, res) => {
const result = createUserSchema.safeParse(req.body)
if (!result.success) {
return res.status(400).json({ errors: result.error.issues })
}
// result.data 类型安全
const user = await db.user.create({ data: result.data })
res.json(user)
})// apps/web/components/CreateUserForm.tsx
import { createUserSchema } from "@shared/schemas/user"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
const form = useForm({
resolver: zodResolver(createUserSchema),
})2. 环境变量校验
// env.ts
import { z } from "zod"
const envSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url().optional(),
JWT_SECRET: z.string().min(32),
PORT: z.coerce.number().int().min(1).max(65535).default(3000),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
})
export const env = envSchema.parse(process.env)3. 错误消息格式化
import { z } from "zod"
import { fromZodError } from "zod-validation-error"
try {
z.object({ name: z.string() }).parse({ name: 123 })
} catch (error) {
if (error instanceof z.ZodError) {
const validationError = fromZodError(error)
console.log(validationError.message)
// "Validation error: Expected string, received number at \"name\""
}
}4. Schema 组合与复用
// 基础 Schema
const baseSchema = z.object({
id: z.string().uuid(),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
})
// 扩展 Schema
const userSchema = baseSchema.extend({
name: z.string(),
email: z.string().email(),
})
// 部分 Schema(用于 PATCH)
const patchUserSchema = userSchema.partial().omit({ id: true, createdAt: true })
// Pick 特定字段
const userSummarySchema = userSchema.pick({ id: true, name: true })5. 常见陷阱
- ❌ 不要在 Schema 中使用
z.any():z.any()破坏了类型安全,应该使用z.unknown()并进行后续校验 - ❌ 不要忘记
.safeParse()的错误处理:忽略result.success === false的情况会导致未校验的数据流入业务逻辑 - ❌ 不要重复定义 Schema:对于复用频率高的数据结构,抽取为独立的 Schema 模块
- ✅ 使用
z.coerce处理字符串到数字/日期的转换:z.coerce.number()比z.string().transform(Number)更简洁 - ✅ 善用
.pipe()进行数据转换链:将校验和转换分离,保持 Schema 的清晰性
技术局限与边界
已知限制
- TypeScript 编译开销:复杂的嵌套 Schema(深层 union + intersection + recursive)可能导致
tsc编译时间显著增加。v4 已大幅优化,但极复杂的 Schema 仍需注意 - 包体积非最小:虽然 v4 缩小了 57%,但完整 Zod 仍约 57KB(min+gzip),对包大小极度敏感的场景应使用
@zod/mini或 Valibot - 不支持 JSON Schema → Zod:Zod 提供 Zod → JSON Schema 的转换,但反向转换(JSON Schema → Zod)需要第三方工具
- 运行时校验不等于类型守卫:
z.infer推导的类型在运行时不存在,TypeScript 的类型系统无法在运行时强制执行 - v3 → v4 迁移成本:虽然支持渐进迁移(
import { z } from "zod/v4"),但.default()行为变更、错误 API 统一等 Breaking Changes 需要仔细处理
不适用场景
- 纯 JavaScript 项目:Zod 的核心价值在于 TypeScript 类型推导,纯 JS 项目无法利用这一特性(虽然运行时校验仍然有效),此时 Joi 或 Yup 可能更合适
- 极致包大小要求:如果每个 KB 都很关键(如 CDN 加载的小脚本),考虑 Valibot 的 Tree-shakable 方案
- 非结构化数据校验:Zod 擅长结构化数据(对象、数组)校验,对于纯文本内容校验(如 HTML 净化)需要额外工具
- GraphQL Schema 定义:GraphQL 有自己的 Schema 定义方式,Zod 不适合直接定义 GraphQL 类型
迁移注意事项
- v3 → v4 渐进迁移:通过
import { z } from "zod/v4"可以在同一项目中混用 v3 和 v4,逐步迁移 - Breaking Changes(v3 → v4):
.default()与 optional 属性的交互行为变更- 统一错误 API(
ZodError结构有调整) z.interface()被移除(功能合并到z.object())- 部分内部 API 变更
- 社区 codemod 工具:zod-v3-to-v4 可辅助自动迁移
学习资源
- 官方文档:https://zod.dev
- v4 发布说明:https://zod.dev/v4
- v4 迁移指南:https://zod.dev/v4/changelog
- v4 版本说明:https://zod.dev/v4/versioning
- JSON Schema 文档:https://zod.dev/json-schema
- GitHub 仓库:https://github.com/colinhacks/zod
- GitHub Releases:https://github.com/colinhacks/zod/releases
- LogRocket 深度解析:https://blog.logrocket.com/zod-4-update/
- InfoQ 报道:https://www.infoq.com/news/2025/08/zod-v4-available/
- PkgPulse 对比文章:https://www.pkgpulse.com/guides/zod-vs-yup-vs-valibot-2026
- DEV 迁移指南:https://dev.to/pockit_tools/migrating-to-zod-4-the-complete-guide-to-breaking-changes-performance-gains-and-new-features-3ll0
- Hacker News 讨论:https://news.ycombinator.com/item?id=44030850
- Reddit r/typescript:https://www.reddit.com/r/typescript/comments/1kqka6e/introducing_zod_4/
- tRPC 文档(Zod 集成):https://trpc.io/docs/validator
2026 年现状
最新版本
- v4.4.0:最新稳定版本,持续优化 JSON Schema 生成和元数据处理
- v4.0.0(2025 年 5 月):里程碑版本,性能提升 14 倍,包体积缩小 57%
- v3.25.x:v3 的最终维护版本,与 v4 共存于同一个 npm 包中
发展趋势
- 性能持续优化:v4 之后仍在持续优化解析性能和 tsc 编译速度
- JSON Schema 生态中心:内置 JSON Schema 转换使 Zod 成为 API 文档和 OpenAPI 规范的核心工具
- AI 时代的数据校验:Zod 在 LLM 输出校验(Structured Output)场景中越来越重要,成为 AI 应用中校验模型输出事实标准
- 标准化推动:Zod 推动了 JavaScript Schema 校验接口的标准化讨论(Standard Schema)
社区活跃度
- GitHub Stars:约 43,000+
- npm 周下载量:约 1 亿+(截至 2026 年,是 npm 上下载量最大的校验库之一)
- GitHub Issues / Discussions 高度活跃
- 贡献者约 470+,生态扩展包持续增长
- 在 tRPC、Next.js、Fastify、Hono 等主流框架中作为默认或推荐的校验方案
未来路线图
- JSON Schema 生成的持续完善(更多 Schema 类型支持、更好的元数据映射)
@zod/mini的 API 完善和功能对齐- Standard Schema 规范的推进和生态采纳
- 性能基准的持续监控和优化
- 更丰富的第三方集成(更多 ORM、API 框架、表单库)