Fastify+TypeBox构建POST校验schema报错unknown keyword 'kind'
错误产生原因
- Fastify 默认基于 Ajv 实现 JSON Schema 校验,Ajv 默认开启严格模式,仅支持标准 JSON Schema 定义的关键字。
@sinclair/typebox生成的 Schema 对象默认携带kind、modifier等框架内部使用的元数据字段,这些字段不属于标准 JSON Schema 规范,Ajv 无法识别就会抛出FST_ERR_SCH_VALIDATION_BUILD错误。
修复方案
方案一(官方推荐):使用 TypeBox 专属类型提供器
这是 Fastify 官方适配 TypeBox 的标准方案,除了解决校验报错,还能自动推导请求、响应的 TypeScript 类型,不需要手动定义请求类型接口。
- 安装适配依赖:
npm install @fastify/type-provider-typebox
- 调整路由代码,在插件中注册类型提供器:
import { FastifyPluginAsync } from 'fastify'; import { Static, Type } from '@sinclair/typebox'; import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'; const User = Type.Object({ name: Type.String(), mail: Type.Optional(Type.String({ format: "email" })), }); type UserType = Static<typeof User>; const root: FastifyPluginAsync = async (fastify, opts): Promise<void> => { // 注册TypeBox类型提供器,自动处理Schema中的非标准元数据 const app = fastify.withTypeProvider<TypeBoxTypeProvider>(); app.get('/', async function (request, reply) { return { root: true } }); app.post('/user', { schema: { body: User, response: { 200: User } } }, async (request, reply) => { request.log.info("User Name: " + request.body.name); request.log.info("User Mail: " + request.body.mail); return { ...request.body }; }); } export default root;
方案二(无额外依赖):序列化剔除非标准字段
如果不想引入额外依赖,可以通过JSON序列化的方式自动剔除TypeBox生成的非标准元数据字段,得到符合标准的JSON Schema:
const reqOpts: RouteShorthandOptions = { schema: { // 序列化后会自动忽略kind、modifier等内部字段,返回纯标准Schema body: JSON.parse(JSON.stringify(User)) } };
该方案需要手动维护请求、响应的TypeScript类型,没有自动类型推导能力。
内容的提问来源于stack exchange,提问作者Sibaprasad Maiti
相关产品推荐
相关产品推荐

