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

为何带索引签名的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:17:25