You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:03:20