TypeScript-first 的运行时 schema 声明与校验库(colinhacks/zod,MIT,43.5k stars,112k+ dependents,当前 v4.4.3)。核心卖点:一份 schema 定义同时得到运行时校验和静态类型推断,消除”TS 类型 + 校验规则两处维护”的漂移问题。
解决的问题
TypeScript 类型只存在于编译期,运行时被完全擦除。程序边界处的数据(API 响应、环境变量、表单提交、LLM/MCP 工具输出)进入后 as User 只是自欺欺人。zod 在运行时真正校验,且校验通过后的数据自带完整 TS 类型——“trust-based programming” 变成 “verify-then-type”。
核心机制
import { z } from "zod";
// 定义 schema(唯一事实来源)
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
role: z.enum(["admin", "user"]).default("user"),
});
// 静态类型推断 —— 不需要手写 interface
type User = z.infer<typeof UserSchema>;
// 运行时校验,两种风格
const user = UserSchema.parse(input); // 失败抛 ZodError
const res = UserSchema.safeParse(input); // 失败返回 { success: false, error }
if (res.success) res.data; // 类型收窄为 User要点:
z.infer<typeof X>是核心:schema 改了类型自动跟着变,不存在类型与校验规则分叉- 链式声明 + 组合:基础类型(string/number/boolean/date/bigint)→ 组合器(object/array/tuple/record/map/set)→ 联合(union/intersection/discriminatedUnion)
- 变换与精化:
.transform()校验后变换输出类型;.refine()/.superRefine()自定义断言(异步 refine 也支持) - 零依赖、同构:Node / 浏览器 / Edge runtime 通用,这是它成为大量框架底座的原因
典型场景
| 场景 | 用法 |
|---|---|
| LLM / MCP 工具入参 | @modelcontextprotocol/sdk 直接用 zod 定义 tool inputSchema,事实标准 |
| API 框架 | tRPC、Next.js server actions、Remix、fastify-zod-schema、Hono 原生集成 |
| 配置加载 | 启动时 parse process.env / 配置文件,非法即 fail-fast |
| 表单校验 | react-hook-form 官方推荐 zodResolver |
| Schema 互转 | v4 内置 z.toJSONSchema() 把 zod schema 转 JSON Schema |
v4 架构(monorepo,本地 clone 精读)
源码副本:~/6ai/opensources/zod(shallow)。pnpm workspace monorepo,packages/zod 为核心,另有 bench/docs/tsc/treeshake/integration/resolution 等基准与集成测试包。
packages/zod/src/
├── v3/ # v3 兼容层(旧代码平滑迁移)
├── v4/core/ # v4 内核
│ ├── core.ts # $constructor + _zod trait 机制(193 行)
│ ├── schemas.ts # 全部 schema 类型实现(4932 行)
│ ├── api.ts # 公开 API 入口 z.string() 等(1840 行)
│ ├── checks.ts # 内置校验检查库(1294 行)
│ ├── parse.ts # parse/safeParse 执行管道
│ ├── standard-schema.ts # Standard Schema 规范接口
│ └── to-json-schema.ts # zod → JSON Schema 转换
├── mini/ # zod/v4/mini:tree-shakable 精简版
├── compile.ts # AOT 编译 side-effect 入口
└── locales/ # 国际化错误消息
关键实现点:
_zodtrait 模式:每个 schema 实例挂一个非枚举的_zod内部对象(def/traits/deferred/values/pattern),懒派生字段通过原型链缓存一次而非每实例重复计算——v4 性能优化(string 14x / array 7x / object 6.5x)的来源之一- Standard Schema:zod 核心维护者共同发起的跨库 schema 互操作规范(
~standard.validate接口),让校验库可互相替换 - 导出映射分层:
.(默认 v4)、./v3、./v4/mini、./compile、./locales/*——v3/v4 共存于同一包,渐进迁移
AOT 编译(zod/compile)
v4 后期加入的预编译能力:import "zod/compile" 是纯 side-effect 模块,向 globalConfig 安装 postProcessor,此后构造的所有 schema 在首次 parse 时编译为纯校验函数(跳过解释执行开销,官方宣称最高 60x,对标 AJV 的速度)。
设计细节:
- 模块求值顺序敏感:只编译该 import 之后构造的 schema,应放应用入口最前
- 失败安全:编译失败(async refinement、不支持特性)自动回退原 runtime parser,调用方无感知
- 配套 Vite 插件支持 autoDiscover 零侵入模式(构建期扫描编译,不改业务代码)
版本要点
- v4(2025 年中稳定):重写内核,性能与类型实例化大幅优化,
zod/v4/minitree-shaking 友好 - v3 仍经
zod/v3子路径维护兼容 - 要求 TypeScript 5.5+,tsconfig 开
"strict": true
相关页面
- botmux — WorkflowDefinition 用 zod 做 schema 验证的真实用例(
parseWorkflowDefinition叠加 DAG 图校验) - README — dependencies 中业务运行时 SDK 的典型成员
- npx-quickstart — 不装直接试用:
npx tsx配合 zod 脚本
资源
- 官网:https://zod.dev
- GitHub:https://github.com/colinhacks/zod(43.5k stars)
- 本地源码:
~/6ai/opensources/zod