← 中文资源

简体中文版本

Fastify Zod 类型提供者

在 Fastify 注册 Zod 类型提供者:一个 schema 同时驱动请求校验、响应序列化与路由处理器的参数类型推断。

阅读英文原文

示例说明

Fastify 的 schema 机制把校验与序列化前移到路由注册时:请求进来先过校验,处理器拿到的 body 已是窄化类型;响应走快速序列化器,多余字段自动剥离。接入 Zod 类型提供者后,schema 从 JSON Schema 换成 Zod 定义,类型推断直接跟随——校验规则、运行时检查与 TypeScript 类型三者出自同一份声明。

技术要点

  • withTypeProvider 挂载 Zod 推断能力
  • body 与各状态码响应共用一套 schema
  • 响应多余字段在序列化时被剥离

代码解读

CreateOrderSchema 用嵌套对象分别约束 body 与 201、400 两种响应形态;处理器里 request.body 的类型由 body schema 推断,SKU 与数量直接解构使用。售罄分支返回 400 结构,成功分支按 201 schema 构造回执,非法数量在进入处理器前已被拦截。

使用建议

schema 复杂度高时拆分为可组合的 Zod 片段。响应 schema 要覆盖全部可能状态码否则序列化会放行未声明形态。此模式与 OpenAPI 生成插件配合可直接产出文档。

代码示例

import Fastify from 'fastify';
import type { ZodTypeProvider } from 'fastify-type-provider-zod';
import { z } from 'zod';

const app = Fastify({
  logger: true,
}).withTypeProvider<ZodTypeProvider>();

const CreateOrderSchema = z.object({
  body: z.object({
    sku: z.string().min(3),
    quantity: z.number().int().min(1).max(99),
  }),
  response: {
    201: z.object({ id: z.string().uuid(), total: z.number() }),
    400: z.object({ error: z.string() }),
  },
});

app.post('/orders', { schema: CreateOrderSchema }, async (request, reply) => {
  const { sku, quantity } = request.body;

  if (sku === 'SOLD-OUT') {
    return reply.code(400).send({ error: 'sku unavailable' });
  }
  return reply.code(201).send({
    id: crypto.randomUUID(),
    total: quantity * 19.9,
  });
});

await app.listen({ port: 3000 });