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

TypeScript:如何为合并Holder实例的combineHolders函数正确标注类型

如何为combineHolders函数正确标注TypeScript类型并支持嵌套合并

当然可以!我们可以通过TypeScript的条件类型、递归类型和泛型来完美解决这个问题,不仅能正确标注combineHolders函数的类型,还能自然支持嵌套结构的合并。下面一步步来实现:

1. 定义基础Holder类及示例

首先我们先明确Holder类的结构(假设它持有一个泛型值),并创建一些实例和嵌套的HoldersObject:

class Holder<T> {
  constructor(public value: T) {}
}

// 单个Holder实例
const nameHolder = new Holder<string>("Alice");
const ageHolder = new Holder<number>(30);

// 嵌套的HoldersObject
const userHolders = {
  name: nameHolder,
  age: ageHolder,
  address: {
    street: new Holder<string>("Main St"),
    city: new Holder<string>("New York")
  }
};

2. 实现ExtractGeneric工具类型

我们需要一个工具类型来提取Holder<T>中的泛型参数T,这是后续合并类型的基础:

// 从Holder实例中提取它持有的值类型
type ExtractGeneric<H> = H extends Holder<infer T> ? T : never;

这个类型利用TypeScript的条件类型+infer关键字,自动推断并提取Holder的泛型参数。

3. 实现递归的CombineHolders类型

接下来需要一个递归类型,用来将嵌套的HoldersObject转换为合并后的目标类型——它会遍历对象的每个键,递归处理嵌套结构:

// 递归处理HoldersObject,将每个Holder替换为对应的值类型
type CombineHolders<T> = {
  [K in keyof T]: T[K] extends Holder<any> 
    ? ExtractGeneric<T[K]> 
    : T[K] extends object 
      ? CombineHolders<T[K]> 
      : T[K]
};
  • 如果当前值是Holder实例,就用ExtractGeneric提取它的值类型;
  • 如果当前值是普通对象(非Holder),就递归调用CombineHolders处理这个嵌套对象;
  • 其他类型则保持原样。

4. 为combineHolders函数标注类型并实现逻辑

现在可以给combineHolders函数添加泛型标注,同时实现递归合并的逻辑:

function combineHolders<T extends Record<string, any>>(holders: T): Holder<CombineHolders<T>> {
  const combined: Record<string, any> = {};

  for (const key in holders) {
    const current = holders[key];
    if (current instanceof Holder) {
      // 如果是Holder实例,直接提取value
      combined[key] = current.value;
    } else if (typeof current === 'object' && current !== null) {
      // 如果是嵌套对象,递归合并后提取value
      combined[key] = combineHolders(current).value;
    } else {
      // 非对象非Holder的类型直接保留
      combined[key] = current;
    }
  }

  return new Holder(combined);
}

函数的泛型T约束为键值对对象,返回类型是Holder<CombineHolders<T>>——TypeScript会自动根据输入的HoldersObject推断出合并后的精确类型。

测试效果

现在我们可以测试一下,TypeScript会完美推断出合并后的类型,包括嵌套结构:

const combinedUser = combineHolders(userHolders);

// TypeScript能正确推断出:
// combinedUser: Holder<{
//   name: string;
//   age: number;
//   address: {
//     street: string;
//     city: string;
//   }
// }>

console.log(combinedUser.value.name); // 类型推断为string
console.log(combinedUser.value.address.city); // 类型推断为string

这样不仅完成了类型标注,嵌套结构的合并也自然实现了——递归类型和递归函数逻辑完美匹配,保证了类型安全和运行时行为一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:45:01