使用trpc-openapi生成OpenAPI文档时遇Input parser必须为ZodObject错误
问题分析与解决办法
问题原因
你碰到的报错不是bug,是trpc-openapi目前不支持把Zod Union(联合类型)作为路由的输入Schema。因为OpenAPI规范本身对请求参数/请求体的定义是基于单一对象结构的,没法直接映射Zod联合这种“二选一”的输入逻辑,所以trpc-openapi会强制要求输入Schema是ZodObject类型。
可行解决方案
方案1:用带校验的单一对象替代联合类型
把原来的两个联合对象合并成一个,将id和key设为可选字段,再通过refine添加二选一的校验逻辑,既满足业务需求,又符合trpc-openapi的要求:
const inputSchema = z.object({ id: z.string().optional(), key: z.string().optional(), }).refine(data => { // 确保只能提供id或key中的一个,不能同时提供或都不提供 const hasId = !!data.id; const hasKey = !!data.key; return hasId !== hasKey; }, { message: "必须且只能提供id或key其中一个参数", path: hasId ? ["key"] : ["id"], });
方案2:拆分路由
如果业务上允许,直接把原来的单个路由拆成两个独立路由:一个接收id参数,一个接收key参数,各自使用单独的ZodObject输入Schema:
// 接收id的路由 const thingByIdRouter = t.procedure .input(z.object({ id: z.string() })) .query(async ({ input }) => { /* 业务逻辑 */ }); // 接收key的路由 const thingByKeyRouter = t.procedure .input(z.object({ key: z.string() })) .query(async ({ input }) => { /* 业务逻辑 */ }); // 合并到主路由 const trpcAppRouter = t.router({ thingById: thingByIdRouter, thingByKey: thingByKeyRouter, });
这种方式最贴合OpenAPI的设计理念,生成的文档也更清晰。
方案3:临时绕过(不推荐)
如果紧急需要生成文档,可临时把输入Schema改成z.object({})或者z.any(),但这样会丢失类型校验,生成的OpenAPI文档也没有参数定义,只适合临时测试用:
// 不推荐,仅临时用 const inputSchema = z.object({});
内容的提问来源于stack exchange,提问作者HMR
相关产品推荐
相关产品推荐

