为何带索引签名的TypeScript接口丢失属性?tRPC类型问题求助
问题解答
这是TypeScript的类型推断行为导致的,并非tRPC的问题。
原因分析
你的ITest接口定义存在类型兼容性冲突:
- 索引签名
[key: string]: object | unknown要求所有字符串键的属性必须属于object | unknown类型; - 具体属性
prop: string虽属于unknown,但当你返回{ prop: "test" }字面量时,TypeScript会对其进行类型窄化,结合索引签名的限制,最终生成了{ [x: string]: never; [x: number]: never; }这种不符合预期的收缩类型; - tRPC的
inferRouterOutputs基于TypeScript对返回值的推断结果生成类型,因此会继承这个错误的收缩类型。
解决方案
方案1:修正ITest接口的类型兼容性
调整索引签名类型,使其与具体属性类型兼容:
interface ITest { [key: string]: unknown; // 改为unknown,兼容string类型 prop: string; }
如果不需要索引签名,直接删除即可,只保留prop: string,类型推断会更准确。
方案2:显式指定procedure的输出Schema
通过tRPC的output方法,用Zod定义输出的类型结构,强制tRPC使用你期望的类型:
export const appRouter = router({ foo: procedure .input(z.undefined()) .output(z.object({ prop: z.string() })) // 直接定义输出结构 // 或者复用ITest:.output(z.custom<ITest>()) .query(() => { let test: ITest = { prop: "test" }; return test; }), });
方案3:返回时显式断言类型
在返回值处用类型断言告诉TypeScript返回的是ITest类型:
export const appRouter = router({ foo: procedure.input(z.undefined()).query(() => { let test: ITest = { prop: "test" }; return test as ITest; // 显式断言 }), });
内容的提问来源于stack exchange,提问作者SimHoZebs
相关产品推荐
相关产品推荐

