如何在TypeScript中基于已有类型创建TResponse泛型类型?
TypeScript泛型类型
TResponse<T>实现方案 现有类型定义
type TUser= { id: number, name: string, } type TFields = { value: number, name: string, otherField: string, } type TTask = { id: number, title: string, } type TDataMethod = { "TFields": "fields", // 修正原定义的笔误:类型为TFields,对应key应为"TFields" "TTask": "tasks", }
需求说明
需要实现泛型类型TResponse<T>,满足:
- 当
T为TUser时,data字段是TUser[]数组类型 - 当
T为TTask或TFields时,data字段是一个对象,键名对应TDataMethod中对应类型名的映射值,值为T类型
正确实现方案
原伪代码的问题在于TDataMethod[T]无法直接通过类型T获取对应键名——TDataMethod的key是类型名称的字符串字面量,而非类型本身。我们可以通过条件类型结合映射逻辑实现需求:
方案一:基于TDataMethod映射的通用写法
// 建立类型到TDataMethod键名的关联 type TypeToMethodKey<T> = T extends TUser ? never : T extends TFields ? "TFields" : T extends TTask ? "TTask" : never; type TResponse<T> = { data: T extends TUser ? TUser[] : { [K in TDataMethod[TypeToMethodKey<T>]]: T }; time: string; };
方案二:直接分支判断的简洁写法
如果类型分支较少,也可以直接写条件判断,可读性更强:
type TResponse<T> = { data: T extends TUser ? TUser[] : T extends TTask ? { tasks: T } : T extends TFields ? { fields: T } : never; time: string; };
验证示例
// 符合预期,无类型错误 const userResponse: TResponse<TUser> = { data: [ {id: 1, name: "John"}, ], time: "13 august 2022" } // 符合预期,无类型错误 const taskResponse: TResponse<TTask> = { data: { tasks: { id: 1, title: "Some task", } }, time: "14 august 2022" } // TFields场景验证 const fieldsResponse: TResponse<TFields> = { data: { fields: { value: 1, name: "test", otherField: "extra" } }, time: "15 august 2022" }
关于是否只能使用extends
不是只能用extends,但在TypeScript的类型系统中,extends是实现这种分支逻辑最直接、最常用的方式。TypeScript的条件类型(Conditional Types)语法本身就基于extends,所有类型分支判断的核心逻辑都依赖它。如果想减少嵌套,也可以通过辅助映射类型优化,但本质上还是离不开条件类型的extends判断。
内容的提问来源于stack exchange,提问作者foxhable
相关产品推荐
相关产品推荐

