跳到主要内容

运行时校验库选型:Zod、Valibot、ArkType、TypeBox 等

一提运行时校验,很多人先想到的就是 zod。这不奇怪,它现在差不多已经成了 TypeScript 项目的默认答案。

但默认选项不等于唯一选项。

但默认答案不等于唯一答案。

项目一旦开始碰到下面这些事,就该把视野放宽一点:

  • 前端包体积是不是太大
  • schema 能不能直接接 JSON Schema / OpenAPI
  • 语法能不能更接近 TypeScript 本身
  • 表单、接口、环境变量、AI 输出到底该用哪种风格统一

这时候,把几类常见方案放在一起看,通常比继续凭感觉选更省事。

这一篇不打算把所有库都扫一遍,只聊今天还值得和 zod 摆在一张桌子上比较的几条路线。

先给个能直接拿走的版本

如果你现在就想定个大方向,可以先看这几句:

1. 大多数普通 TypeScript 项目

先用 zod,多数时候都不会错。

原因很简单:

  • 心智成本低
  • 社区例子多
  • 表单、AI、服务端入口、环境变量这些场景都能覆盖
  • 生态配套最稳

2. 前端更在意包体积

优先看 Valibot

它和 zod 解决的是同一类问题,只是更强调模块化和体积。

3. 想要更贴近 TypeScript 语法

优先看 ArkType

它最抓人的地方不是功能堆得多,而是写 schema 时真的更像在写类型。这点和 zod 的区别很明显。

4. 后端强依赖 JSON Schema / OpenAPI / 跨语言契约

优先看 TypeBox + Ajv

这一套更偏标准协议,不是前端熟悉的那种链式 API 手感。

5. 老项目表单体系已经很多

可能还会继续留在 Yup

不是因为它更先进,而是很多时候迁移回报不够高。

6. Node 后端里复杂条件校验很多

可以看 Joi

它不是现在最热的选择,但在服务端复杂校验这块,依然很稳。

对比表

更像哪一派更适合什么场景你要先知道的特点
Zod通用默认派大多数 TS Web 项目生态稳、文档多、链式 API 顺手
Valibot轻量版 Zod前端、表单、对体积敏感模块化、体积更小、迁移心智低
ArkTypeTS 语法派想把类型表达和运行时校验贴更近定义方式更像类型声明,函数边界校验也很亮眼
TypeBoxJSON Schema 派OpenAPI、后端协议、跨语言契约schema 本身就是 JSON Schema
Ajv高性能校验器派大规模 JSON Schema 校验更像校验引擎,不是 DX 友好的 schema DSL
Yup老牌表单派历史 React 表单项目老生态成熟,今天新项目通常没那么优先
JoiNode 服务端派复杂后端校验、条件关系多表达力强,TS 一体感弱于 zod
Superstruct轻量简单派小项目、轻量边界校验API 简单直接,不走大生态路线

1. Zod:今天最稳的默认选项

Zod 官方一直强调两件事:一是开发体验和体积之间做平衡,二是 schema API 尽量贴着 TypeScript 类型系统走。

这也是它今天最大的优势。它不一定每一项都冲到最前面,但整体没有明显短板。

适合它的场景

  • 你不想在选库这件事上花太多时间
  • 你需要文档、生态、社区例子都足够多
  • 你要同时覆盖接口层、表单、环境变量、AI 输出

它的短板通常在哪

  • 如果你很在意前端包体积,它不一定是最轻的
  • 如果你想直接以 JSON Schema 为中心建契约,它不是最自然的那条路
  • 如果你希望定义体验更接近原生 TS 类型表达,ArkType 会更像

想单独看 zod,继续读 运行时校验与 Zod

2. Valibot:如果你喜欢 Zod,但又想更轻

Valibot 官方把自己定义成“模块化、类型安全的 schema 库”,强调可以用于服务端输入、表单和配置文件,同时重点提到体积小、无依赖、可 tree-shake。

它和 zod 不是完全不同的路子,更像是在同一个问题上换了一种更细颗粒度的写法。

什么时候优先看它

  • 你已经确认项目里会大量在浏览器侧跑校验
  • 你对 bundle size 比较敏感
  • 你喜欢把校验动作拆成更细的小函数组合

和 Zod 的直觉差别

zod 更像:

z.string().min(1).email()

Valibot 更像:

v.pipe(v.string(), v.minLength(1), v.email())

谁更顺手,通常取决于你喜欢链式写法,还是喜欢把动作拆开。

3. ArkType:最像在“直接写 TypeScript”

如果只看“写起来像不像 TypeScript 类型本身”,ArkType 大概是这一组里最特别的一个。

官方文档一上来就直接写这种例子:

const User = type({
name: "string",
platform: "'android' | 'ios'",
"versions?": "(number | string)[]"
})

它更像是把类型表达直接带进了运行时,而不是再学一套链式校验器。

而且最近版本还补了几件很有辨识度的能力:

  • type.fn:把函数参数和返回值一起做运行时校验
  • JSON Schema 双向互通
  • 可以嵌入其他 Standard Schema 风格的 validator

它更适合谁

  • 你本来就很吃 TypeScript 类型表达这一套
  • 你不喜欢链式 API 越写越长
  • 你想把“函数边界”也一起纳入校验

它和 Zod 的关键区别

Zod 更像一套通用、成熟、很好上手的 schema builder。

ArkType 更像把 TypeScript 风格的类型表达直接跑起来。

如果你想单独看这条线,再读 ArkType:最接近 TypeScript 的运行时校验

4. TypeBox + Ajv:标准协议路线

TypeBox 官方的说法很直接:它会创建内存中的 JSON Schema 对象,再从里面推导 TypeScript 类型。

所以它天然更适合这种工作方式:

  • 先把 schema 当成标准 JSON Schema 资产
  • 再把类型推导当成附带收益

Ajv 则更像这一套里的高性能发动机。官方文档强调它会把 schema 编译成高效的 JavaScript 校验函数。

什么时候它比 Zod 更顺

  • 你要直接对接 OpenAPI / JSON Schema 工具链
  • schema 需要跨语言共享
  • 你在后端更看重标准协议和性能
  • 你不介意 DX 没有 zod 那么“前端化”

不太适合它的情况

  • 只是普通前端表单和接口层,不需要协议级标准化
  • 团队成员更习惯 zod 这类链式写法

5. Yup:还在用,但更多是历史延续

Yup 官方现在也强调自己支持运行时解析、校验、转换和 TypeScript 推导。

它不是不能用,问题主要在这里:

  • 新项目里,它通常不再是最自然的第一选择
  • 现在很多团队在 zodvalibot 之间就能解决大多数问题

什么时候继续用它是合理的

  • 你已经有一大套基于 Yup 的表单体系
  • 团队里对它很熟
  • 当前收益不够大,不值得大迁移

6. Joi:Node 服务端老将

Joi 官方把自己定义成一个强表达力的 schema description language 和 data validator。

它的优势一直不是“像 TypeScript”,而是:

  • 内建规则很多
  • 跨字段关系和条件逻辑表达成熟
  • 错误信息细,路径也清楚

它更像什么场景

  • Node 服务端接口
  • 配置校验
  • 复杂条件约束很多的业务对象

如果团队主要是前端出身,第一次上手 Joi 往往会觉得:能用,也很强,只是没 zod 那么顺手。

7. Superstruct:轻量直接

Superstruct 的特点是 API 比较直,学习成本低,也支持默认值、断言和类型守卫式判断。

它的问题不在功能不够,而在于今天大家讨论得更多的是 zod / valibot / arktype / typebox。所以它更像一个轻量、安静,但没那么站在风口上的选择。

如果团队里要定一个默认答案

我会建议这样定:

默认方案

Zod

例外 1:前端包体积明显敏感

改看 Valibot

例外 2:团队特别吃 TypeScript 类型表达

改看 ArkType

例外 3:后端契约强依赖 JSON Schema / OpenAPI

改看 TypeBox + Ajv

例外 4:存量项目已经深度绑定 Yup 或 Joi

先别急着重写,先看迁移到底值不值。

推荐阅读

官方文档