TRPC中匿名函数的重载语法及代码放置位置咨询
TRPC路由中匿名函数的重载实现方案
一、匿名函数的重载语法
匿名函数没法直接用function关键字的重载声明方式,得通过类型定义+类型断言,或者条件类型来模拟重载行为:
- 方式1:先定义包含重载签名的类型,再把匿名函数断言为该类型
- 方式2:用泛型条件类型直接约束输入与返回值的对应关系
二、TRPC场景下的代码放置位置
TRPC的query回调函数的重载逻辑,需要结合Zod输入校验的结果,通过TypeScript类型系统关联输入和返回值。具体可以:
- 提前定义重载类型,再将回调函数断言为该类型
- 直接在回调函数的参数/返回值上使用条件类型,让TS自动推导类型关联
三、你的两种写法分析
写法1:重载签名类型
type IOverload = { (input: { id?: undefined | null }): Promise<IPosts[]>; (input: { id: string }): Promise<IPost>; }
这个类型逻辑是可行的,但需要调整参数匹配你的实际输入(你的输入是{ id: string | null | undefined } | null)。之后可以把query的回调函数断言为这个类型来生效。
写法2:条件类型函数
type QueryFn = <T extends { id?: string | null } | null>( input: T ) => Promise<T extends { id: string } ? IPost : IPosts[]>;
这种写法也可行,通过泛型条件类型直接关联输入和返回值,不需要额外类型断言,TS会自动根据输入类型推导返回值类型。
四、完整实现示例
结合你的现有代码,修改后的正确实现如下:
方式1:使用重载类型断言
// 定义匹配输入输出的重载类型 type PostQueryFn = { (args: { input: null | { id?: undefined | null } }): Promise<IPosts[]>; (args: { input: { id: string } }): Promise<IPost>; }; publicProcedure .input(z.object({ id: z.string().nullish() }).nullish()) .query(async ({ input }) => { const url = "https://example.com/posts"; const json = (await got.get(url).json()) as IPosts[]; if (input && input.id) { const post = json.find(p => p.id === input.id); // 处理find可能返回undefined的情况,这里示例直接断言,实际建议加空值判断或抛出错误 return post as IPost; } return json; } as PostQueryFn); // 将回调函数断言为重载类型
方式2:使用泛型条件类型
publicProcedure .input(z.object({ id: z.string().nullish() }).nullish()) .query(async <T extends null | { id?: string | null }>({ input }: { input: T }) => { const url = "https://example.com/posts"; const json = (await got.get(url).json()) as IPosts[]; if (input && input.id) { const post = json.find(p => p.id === input.id); return post as T extends { id: string } ? IPost : never; } return json as T extends { id: string } ? never : IPosts[]; });
注意点
- 要保证Zod的输入校验规则和TypeScript类型定义一致,避免类型不匹配
Array.find可能返回undefined,建议添加空值处理(比如抛出TRPC错误),让类型更严谨
内容的提问来源于stack exchange,提问作者wongx
相关产品推荐
相关产品推荐

