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

如何从函数参数数组提取类型并生成泛型交叉类型?

提取数组内对象字段的交叉类型作为函数返回值

要实现create函数返回值为传入数组中所有Extension对象fields的交叉类型,核心在于保留数组元素的具体类型信息,并通过泛型工具类型将这些fields类型交叉合并。

解决步骤及代码实现

1. 定义核心工具类型

先实现一个泛型工具类型,用来递归遍历数组元素,提取每个元素的fields并合并为交叉类型:

type Extension = {
  name: string,
  fields: {
    [key: string]: string
  }
}

// 递归拆解数组,将每个元素的fields类型交叉合并
type CombineFields<Ext extends Extension[]> = 
  Ext extends [infer First, ...infer Rest] 
    ? First['fields'] & CombineFields<Rest> 
    : {}

2. 改造create函数的泛型定义

不要使用固定的Config类型(会抹平数组元素的具体类型细节),改用泛型参数让TypeScript自动推导extensions的具体元素类型:

function create<Ext extends Extension[]>(config: { name: string, extensions: Ext }): CombineFields<Ext> {
  // 合并所有fields的逻辑实现
  return config.extensions.reduce((merged, ext) => ({ ...merged, ...ext.fields }), {} as CombineFields<Ext>)
}

3. 正确使用示例

注意不要给ext1/ext2手动指定Extension类型,让TypeScript自动推导它们的具体类型,这样才能保留fields的键名信息:

const ext1 = {
  name: 'ext1',
  fields: {
    field1: 'test',
    field2: 'test'
  }
}

const ext2 = {
  name: 'ext2',
  fields: {
    field3: 'test',
    field4: 'test'
  }
}

const config = {
  name: 'Test',
  extensions: [ext1, ext2]
}

// result的类型自动推导为 {field1: string; field2: string} & {field3: string; field4: string}
const result = create(config)

可选:保留泛型版Config类型

如果需要保留Config类型的定义,可以将其改为泛型形式:

type Config<Ext extends Extension[]> = {
  name: string,
  extensions: Ext
}

function create<Ext extends Extension[]>(config: Config<Ext>): CombineFields<Ext> {
  return config.extensions.reduce((merged, ext) => ({ ...merged, ...ext.fields }), {} as CombineFields<Ext>)
}

关键原理

  • 泛型Ext extends Extension[]让TypeScript保留数组中每个元素的具体类型,避免用Extension[]统一类型导致的细节丢失。
  • CombineFields通过条件类型递归拆解数组结构,将每个元素的fields类型依次交叉合并,最终得到所有字段的联合交叉类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 23:17:05