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

TypeScript如何通过映射类型正确推断合并对象数组后的返回类型

问题原因

原有写法的核心问题有两点:

  • 泛型D的默认值设为ThemeDependency[],TypeScript无法自动推断传入的dependencies数组的具体元组类型,只会将其当做普通的ThemeDependency数组处理,因此读取到的defaults.size类型就是基类ThemeDependency对应的未知类型,最终推导为unknown
  • 额外定义的泛型A默认值为number,无法对应到数组的具体元素索引,即使手动传入数字也无法拿到准确的元素类型

解决方案

1. 定义递归合并工具类型

遍历依赖数组的所有元素,把每个元素的defaults.size做交叉合并,得到最终的components类型:

type MergeDependencySizes<D extends ThemeDependency[]> = 
  // 递归拆分元组,合并每一项的size属性
  D extends [infer First extends ThemeDependency, ...infer Rest extends ThemeDependency[]]
    ? First['defaults']['size'] & MergeDependencySizes<Rest>
    // 递归结束返回空对象
    : {}

2. 改造函数泛型定义

去掉无意义的A泛型,让TypeScript自动推断传入的依赖数组的具体元组类型:

// 不要给D设默认值,让TS自动推断传入的数组具体类型
const stitchTheme = <
  T extends RawTheme,
  D extends ThemeDependency[]
>(
  rawTheme: T,
  dependencies: D,
  options?: StitchThemeOptions
): T & {
  size: T['size'] & {
    components: MergeDependencySizes<D>
  }
} => {
  // 这里写你的实际合并逻辑,把所有dependencies的defaults.size合并到theme.size.components下
  const merged = { ...rawTheme }
  merged.size = { ...merged.size, components: {} }
  dependencies.forEach(dep => {
    Object.assign(merged.size.components, dep.defaults.size)
  })
  return merged as any
}

使用效果

调用时不需要手动传入泛型,TS会自动完成类型推断:

const finalTheme = stitchTheme(theme, [barDependency])
// 此时finalTheme.size.components.bar.foo会被正确推断为number类型
console.log(finalTheme.size.components.bar.foo) // 12

如果你的依赖数组是动态生成的、不是常量元组,可以给ThemeDependency接口加明确的类型约束,避免推断为unknown:

interface ThemeDependency {
  defaults: {
    size: Record<string, any>
    color: Record<string, any>
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:15:00