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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:35:22