TypeBox 比 Zod.js 校验 快10倍, 还兼容AI 工具调用, 他做对了什么?

40岁了,最近再学bun和ai。

上周压测,QPS 一上 1000,CPU 飙到 80%。

查了半天,瓶颈在校验上。

订单提交接口,30 来个字段。

每个字段链式校验 5、6 层。

QPS 一千,每秒 15 万次方法调用。

V8 看着都替它累。

调成 TypeBox + Ajv,编译一次,CPU 直接腰斩。

这就是今天要聊的:解释器 vs 编译器。

Zod 是 TS 圈的校验 老炮,写法爽生态大。TypeBox 是 JSON Schema 派的新秀,速度是 Zod 的 10 到 15 倍。一个解释器 跑、一个编译器编,速度能一样吗。

bash 复制代码
// TypeBox + Ajv:先把 Schema 编译成函数,后面就一泻千里
import { Type, type Static } from '@sinclair/typebox'
import Ajv from 'ajv'
import addFormats from 'ajv-formats'

const UserSchema = Type.Object({
  id: Type.String({ format: 'uuid' }),
  name: Type.String({ minLength: 1 }),
  email: Type.String({ format: 'email' }),
  age: Type.Integer({ minimum: 0, maximum: 150 }),
})

type User = Static<typeof UserSchema>

const ajv = addFormats(new Ajv({ allErrors: true }))
const validate = ajv.compile(UserSchema)   // 编译一次,吃一辈子

const ok = validate({ id: 'xxx', name: '老王', email: 'a@b.com', age: 30 })
console.log(ok)   // true

看着不起眼?

ajv.compile 这一步,才是 TypeBox 快得邪乎的关键。

Zod 是边校验边判断类型,

TypeBox 是先把校验逻辑编译成原生 JS 函数,再去跑数据。

一个解释器,一个编译器。

速度能一样吗?


一句话先看明白这俩玩意儿

Zod 是一套"链式 API 校验库"。TypeBox 是一套"JSON Schema 构建器",顺便送你 TS 类型。

差别在哪?Zod 的 schema 是个自家 ZodObject 实例,得自己跑。TypeBox 的 schema 是个标准的 JSON Schema,能直接喂给 Ajv、Fastify、OpenAPI。

Static<typeof Schema> 一拉,TS 类型也出来了。一鱼三吃:运行时校验、编译时类型、OpenAPI 文档。


一、Zod 慢在哪?老铁先看看这段

Zod 的写法大家都熟:

bash 复制代码
import { z } from 'zod'

const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1),
  email: z.string().email(),
  age: z.number().int().min(0).max(150),
})

const result = UserSchema.safeParse({ id: 'xxx', name: '老王', email: 'a@b.com', age: 30 })
if (result.success) console.log(result.data)

看着是挺爽。z.string().email().min(8),链子一拉完事。但每跑一次校验,它都得逐个判断:

  • • 这是 ZodString 实例吗?

  • • 调 .email() 内部方法。

  • • 调 .min() 内部方法。

  • • 再调 .uuid() 内部方法。

每一个方法都是一次函数调用。100 个字段 100 次方法调用。V8 看着都替你累。


二、TypeBox 是怎么把 Zod 按在地上摩擦的

TypeBox 不做这些虚的。它只负责把 schema 写出来,然后交给 Ajv。

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'
import Ajv from 'ajv'
import addFormats from 'ajv-formats'

const UserSchema = Type.Object({
  id: Type.String({ format: 'uuid' }),
  name: Type.String({ minLength: 1 }),
  email: Type.String({ format: 'email' }),
  age: Type.Integer({ minimum: 0, maximum: 150 }),
})

type User = Static<typeof UserSchema>

const ajv = addFormats(new Ajv({ allErrors: true }))
const validate = ajv.compile(UserSchema)

const data: User = { id: 'xxx', name: '老王', email: 'a@b.com', age: 30 }
console.log(validate(data))   // true

ajv.compile 干了啥?它把上面的 schema,编译成一段优化过的 JS 函数。简单说,就是这么个东西:

bash 复制代码
// 编译产物长这样(简化版)
function validate(data) {
  if (typeof data !== 'object') return false
  if (typeof data.id !== 'string') return false
  if (!/^[0-9a-f-]{36}$/.test(data.id)) return false
  if (typeof data.name !== 'string') return false
  if (data.name.length < 1) return false
  if (!/^.+@.+\..+$/.test(data.email)) return false
  if (typeof data.age !== 'number') return false
  if (data.age < 0 || data.age > 150) return false
  return true
}

全是 typeof、正则、布尔判断。V8 最爱的形状。循环跑起来,CPU 几乎不费力。


三、benchmark 数据,不是嘴炮

我自己跑过,也参考了 sinclair 的官方数据。

100 万次复杂对象校验:

| 库 | 耗时 | 相对速度 | | :-- | :-- | :-- | | TypeBox + Ajv | ~80ms | 1x 基准 | | TypeBox (内置 Compiler) | ~260ms | 慢 3 倍 | | Zod v4 (parse) | ~880ms | 慢 11 倍 | | Zod v3 (parse) | ~1400ms | 慢 17 倍 |

zod v4 比 v3 已经快了不少。但跟 TypeBox + Ajv 比,还是被按在地上摩擦。v3 用户更惨,慢 17 倍。

简单字符串校验的差距更夸张:

bash 复制代码
z.string().email().parse(x)        132 µs
TypeBox + Ajv.compile + 校验       ~10 µs

快 10 倍以上。越简单的校验,TypeBox 优势越明显。


四、再看个真实业务场景

来个电商订单校验。包含嵌套对象、数组、枚举、可选项。

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'
import Ajv from 'ajv'
import addFormats from 'ajv-formats'

const OrderSchema = Type.Object({
  orderId: Type.String({ format: 'uuid' }),
  userId: Type.String(),
  items: Type.Array(
    Type.Object({
      sku: Type.String(),
      qty: Type.Integer({ minimum: 1, maximum: 999 }),
      price: Type.Number({ minimum: 0 }),
    }),
    { minItems: 1, maxItems: 100 }
  ),
  address: Type.Object({
    province: Type.String(),
    city: Type.String(),
    detail: Type.String({ minLength: 5 }),
  }),
  payMethod: Type.Union([
    Type.Literal('alipay'),
    Type.Literal('wechat'),
    Type.Literal('card'),
  ]),
  remark: Type.Optional(Type.String({ maxLength: 200 })),
})

type Order = Static<typeof OrderSchema>

const ajv = addFormats(new Ajv({ allErrors: true, useDefaults: true }))
const validateOrder = ajv.compile(OrderSchema)

const order: Order = {
  orderId: 'xxx',
  userId: 'u001',
  items: [{ sku: 'A001', qty: 2, price: 99.9 }],
  address: { province: '辽宁', city: '沈阳', detail: '和平区南京北街 100 号' },
  payMethod: 'wechat',
}

if (validateOrder(order)) {
  console.log('订单格式没问题')
} else {
  console.log(validateOrder.errors)
}

Zod 写法能短一丢丢,但校验时挨个调方法。TypeBox 写法稍长,编译完就是铁甲。接口越复杂、数据越大,差距越明显。


五、TypeBox 的 JSON Schema 是真家伙

这一条是 TypeBox 真正的杀手锏。

TypeBox 写出来的 schema,就是标准 JSON Schema。所以它能直接对接:

  • Fastify:原生支持 JSON Schema 校验和响应序列化

  • OpenAPI:直接生成 API 文档

  • AI 工具调用:OpenAI、Anthropic、Gemini 全都吃 JSON Schema

  • Ajv:业界最快的 JSON Schema 校验器

  • drizzle-typebox:数据库 schema 转 TypeBox

拿 AI function calling 举个例子:

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'

// 给 AI 用的工具定义
const WeatherTool = {
  name: 'get_weather',
  description: '查询某城市天气',
  parameters: Type.Object({
    city: Type.String({ description: '城市名,比如沈阳' }),
    unit: Type.Union([Type.Literal('c'), Type.Literal('f')], {
      default: 'c',
    }),
  }),
}

type WeatherArgs = Static<typeof WeatherTool.parameters>

// 直接发给大模型
console.log(JSON.stringify(WeatherTool.parameters))
// 输出标准 JSON Schema,OpenAI / Claude / Gemini 都能用

Zod 想做这事?得引入 zod-to-json-schema 包。转出来的还时不时有兼容问题。

TypeBox 一步到位。写一次,三端通用:TS 类型、运行时校验、AI 工具定义。


六、Elysia 默认就集成了 TypeBox

跑过 Elysia 的老铁都知道:那个 21 倍的 Express 性能碾压,靠的就是 TypeBox 加 Ajv 那一套。

Elysia 不用你装,不用你配。装上 elysia 包的那一刻,TypeBox 就已经在里面了 。它直接 fork 了 TypeBox,改了个名叫 Elysia.t

bash 复制代码
import { Elysia, t } from 'elysia'

const app = new Elysia()
  .post('/user', ({ body }) => `Hello ${body.name}`, {
    body: t.Object({
      name: t.String({ minLength: 1 }),
      age: t.Integer({ minimum: 0 }),
      email: t.String({ format: 'email' }),
    }),
  })
  .listen(3000)

body 后面那个 t.Object,就是 TypeBox 原生写法。零成本接入,连 import 都不用改。

Elysia 顺手把 schema 喂给 Ajv,编译成函数缓存起来。请求一来,直接跑函数,零解释开销。

这就是 Elysia 比 Express 快 21 倍的真相之一。不是单点优化,是每一个环节都把解释器换成编译器


七、TypeBox 还能这么玩

你以为 TypeBox 就只能校验?太小看它了。

1. 数据库 schema 一把梭

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'

const UserModel = Type.Object({
  id: Type.String(),
  email: Type.String({ format: 'email' }),
  createdAt: Type.String({ format: 'date-time' }),
})

type User = Static<typeof UserModel>

// 同时给 TS 类型、API 校验、OpenAPI 文档用
// 一份代码,三处生效

2. 条件类型也支持

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'

const PaymentSchema = Type.Object({
  method: Type.Union([Type.Literal('card'), Type.Literal('crypto')]),
  cardNo: Type.Optional(Type.String()),
  wallet: Type.Optional(Type.String()),
})

// 配合 Type.Union + discriminator,TS 类型能精确推断
// card 模式下 wallet 不该有值,TS 会提示

3. 配合 tRPC 玩转 RPC

虽然 tRPC 默认用 Zod。但你想换 TypeBox 也能用,schema 写一遍,前后端通吃。


八、那 Zod 还能用吗?能!

说了这么多 TypeBox 的好。但 Zod 也不是没优势。

Zod 优势:

  • • 链式 API 写起来真的爽,可读性强

  • • 错误信息开箱即用,体验好

  • • 生态最大,tRPC、React Hook Form、Drizzle 默认支持

  • • 新人上手快,半小时能干活

TypeBox 优势:

  • • 速度是 Zod 的 10 到 15 倍

  • • schema 直接是 JSON Schema,三端通用

  • • TypeScript 类型推断更精确

  • • Elysia、Fastify 原生支持

老铁选型建议:

  • • 写普通业务、CRUD,Zod 够用

  • • 写高 QPS 接口、AI 工具、大数据校验,换 TypeBox

  • • 用 Elysia 写 Bun 项目,闭眼选 TypeBox

  • • 用 Fastify 写 Node 项目,TypeBox 完胜


九、上手 TypeBox,三步搞定

第一步:装包。

bash 复制代码
bun add @sinclair/typebox ajv ajv-formats

第二步:写 schema。

bash 复制代码
import { Type, type Static } from '@sinclair/typebox'

const TodoSchema = Type.Object({
  id: Type.String(),
  title: Type.String({ minLength: 1, maxLength: 200 }),
  done: Type.Boolean({ default: false }),
  tag: Type.Optional(Type.String()),
})

type Todo = Static<typeof TodoSchema>

第三步:编译 + 校验。

bash 复制代码
import Ajv from 'ajv'
import addFormats from 'ajv-formats'

const ajv = addFormats(new Ajv({ allErrors: true }))
const validate = ajv.compile(TodoSchema)

const todo = { id: '1', title: '学 TypeBox', done: false }
console.log(validate(todo))   // true

完事。40 岁老哥亲自试过,从 Zod 切到 TypeBox,半小时搞定。后面接口压力小了一半,CPU 占用直接降 30%。


写在最后

TypeBox 不是要干掉 Zod。它俩是不同赛道的工具。

Zod 走"开发者体验"路线。TypeBox 走"性能 + 标准"路线。

你的项目卡在性能上?你对接的是 Fastify、Elysia?你在做 AI 工具调用?

别犹豫,TypeBox + Ajv 安排上。10 到 15 倍的提升,真不是吹出来的。是 Ajv 编译器一行一行编出来的。

老铁,代码写起来吧。别光看,跑一遍才是真的。


参考资料:

  • • TypeBox GitHub

  • • Ajv 官方文档

  • • Elysia TypeBox 模式

  • • Elysia ACM 论文


往期文章

相关推荐
倔强的石头_10 小时前
WorkBuddy 上手实战:打造一个可用的本地 AI 工作台
后端
Bigger10 小时前
Tauri (26)——托盘图标总对不上系统主题?一行 Template Image 搞定
前端·rust·app
To_OC10 小时前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
kyriewen12 小时前
面试官问你:“AI 能写 80% 的代码了,公司为什么还需要你?”
前端·javascript·面试
甲维斯13 小时前
又升级咯!坦克大战2026,科技与复古并存!
前端·人工智能·游戏开发
苍何15 小时前
Coding 真有质的飞跃?实测下豆包seed 2.1 pro
后端
苍何15 小时前
试了下腾讯 Marvis,回不去了...
后端
caibixyy15 小时前
springboot+langchain4j 实战 Day14——工具嵌入多 Agent(Tool-Equipped Multi-Agent)
后端