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

如何实现GetTypeArg类型?提取泛型类型的第N个类型参数

实现 GetTypeArg 类型的方案

要实现能从类型 T 中获取第 N 个泛型参数的 GetTypeArg<T, N>,需要处理两种场景:

  1. 当 T 是未传入泛型参数的泛型类型构造器(比如 X),提取其第 N 个泛型参数的默认值;
  2. 当 T 是传入了泛型参数的具体类型(比如 Y<unknown>),提取其第 N 个泛型参数的实际值(包括默认值)。

方案一:针对特定泛型类型的精确实现

这种方案通过条件类型的 infer 关键字匹配目标泛型类型的实例,同时处理泛型构造器的默认参数提取:

// 辅助类型:将1-based数字转换为0-based索引
type MinusOne<N extends number> = 
  N extends 1 ? 0 :
  N extends 2 ? 1 :
  N extends 3 ? 2 :
  N extends 4 ? 3 :
  N extends 5 ? 4 :
  // 可根据需求扩展更多数字范围
  never;

type GetTypeArg<T, N extends number> =
  // 匹配X的泛型实例,提取对应位置参数
  T extends X<infer A> ? (N extends 1 ? A : never) :
  // 匹配Y的泛型实例,提取对应位置参数
  T extends Y<infer A, infer B> ? (N extends 1 ? A : N extends 2 ? B : never) :
  // 处理泛型构造器,提取默认参数
  (<...Args>() => T<...Args>) extends <...Args>(...args: never[]) => any ? Args[MinusOne<N>] :
  never;

// 测试用例
type X<T = string> = {value: T}
type Y<T,M=number> = {value1: T, value2: M}

type TestX = GetTypeArg<X, 1> // string,符合预期
type TestY1 = GetTypeArg<Y<unknown>, 1> // unknown,符合预期
type TestY2 = GetTypeArg<Y<string[]>, 2> // number,符合预期

方案二:基于属性顺序的通用实现

如果需要不依赖具体泛型类型的通用实现,可以利用对象属性定义顺序来推断泛型参数(TS 2.1+ 会保留字面量对象的属性顺序):

// 辅助类型:将1-based数字转换为0-based索引
type MinusOne<N extends number> = 
  N extends 1 ? 0 :
  N extends 2 ? 1 :
  N extends 3 ? 2 :
  N extends 4 ? 3 :
  N extends 5 ? 4 :
  never;

// 辅助类型:获取对象按定义顺序的第N个属性类型
type GetNthPropertyType<T, N extends number> =
  T extends Record<string, any> ?
    keyof T extends infer Keys ?
      Keys extends string ?
        Array<Keys> extends infer KeyArray ?
          KeyArray[MinusOne<N>] extends infer Key ?
            T[Key] :
          never :
        never :
      never :
  never;

type GetTypeArg<T, N extends number> =
  // 先从具体类型的属性中推断泛型参数
  GetNthPropertyType<T, N> extends infer PropType ?
    PropType extends never ?
      // 再处理泛型构造器的默认参数
      (<...Args>() => T<...Args>) extends <...Args>(...args: never[]) => any ? Args[MinusOne<N>] :
      never :
    PropType :
  never;

// 测试用例
type X<T = string> = {value: T}
type Y<T,M=number> = {value1: T, value2: M}

type TestX = GetTypeArg<X, 1> // string,符合预期
type TestY1 = GetTypeArg<Y<unknown>, 1> // unknown,符合预期
type TestY2 = GetTypeArg<Y<string[]>, 2> // number,符合预期

注意事项

  • 方案一适合已知泛型类型结构的场景,匹配精确但扩展性有限;
  • 方案二更通用,但依赖 TypeScript 对对象属性顺序的保留;
  • MinusOne 类型目前支持1-5的数字,可根据需求扩展更多分支。

内容的提问来源于stack exchange,提问作者kennarddh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:47:35