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/     # 国际化错误消息

关键实现点:

  • _zod trait 模式:每个 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/mini tree-shaking 友好
  • v3 仍经 zod/v3 子路径维护兼容
  • 要求 TypeScript 5.5+,tsconfig 开 "strict": true

相关页面

  • botmux — WorkflowDefinition 用 zod 做 schema 验证的真实用例(parseWorkflowDefinition 叠加 DAG 图校验)
  • README — dependencies 中业务运行时 SDK 的典型成员
  • npx-quickstart — 不装直接试用:npx tsx 配合 zod 脚本

资源