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

如何获取索引访问器属性名?为personZoo配置正确类型

TypeScript动态添加属性的类型推导解决方案

以下是修改后的完整代码,能实现你期望的类型推导效果:

// 泛型IPerson接口,保留name和behavior的具体字面量类型
interface IPerson<Name extends string = string, Behavior extends Record<string, () => string> = Record<string, () => string>> {
  name: Name;
  behavior: Behavior;
}

const personZoo = {
  zooName: "person zoo",
};
type PersonZoo = typeof personZoo;

// 生成合并后的类型:将数组元素的name作为属性名,对应behavior作为属性类型
type MergeReturnType<T, K extends IPerson[]> = T & {
  [P in K[number]['name']]: K[number] extends infer Item 
    ? Item extends IPerson<P, infer B> 
      ? B 
      : never 
    : never;
};

// 调整merge函数泛型,捕获数组元素的具体类型
function merge<T extends IPerson[]>(
  obj1: PersonZoo,
  obj2: readonly [...T],
): MergeReturnType<PersonZoo, T> {
  obj2.forEach((p) => {
    Object.defineProperty(obj1, p.name, {
      get() {
        return new Proxy(p.behavior, {
          get(target, key) {
            return target[key];
          },
        });
      },
    });
  });

  return obj1 as MergeReturnType<PersonZoo, T>;
}

// 去掉宽泛的IPerson[]标注,用as const保留字面量类型
const personArr = [
  {
    name: "n1",
    behavior: {
      loudly: () => "speak loudly",
    },
  },
  {
    name: "n2",
    behavior: {
      singing: () => "singing",
    },
  },
] as const;

const xx = merge(personZoo, personArr);
// 类型推导正常,支持以下调用
xx.n1.loudly();
xx.n2.singing();

问题1:如何获取索引访问器的属性名?

要提取数组元素中name的具体字面量类型,核心是避免丢失类型细节:

  • 不要给personArr标注宽泛的IPerson[]类型——这个类型会让TypeScript把"n1"、"n2"当成普通string,丢失字面量信息;
  • 给数组添加as const断言——强制TypeScript将数组元素的属性值视为不可变的字面量类型,这样就能精准捕获name的具体值。

问题2:如何让personZoo拥有动态添加属性的类型?

通过TypeScript的泛型+映射类型组合实现:

  1. 泛型捕获具体元素类型:merge函数的泛型T会自动捕获personArr中每个元素的完整类型(包括name的字面量和behavior里的具体方法);
  2. 映射类型生成动态属性:MergeReturnType中的[P in K[number]['name']]会遍历数组中所有name值,将其作为新的属性名;
  3. 条件类型提取behavior类型:通过嵌套条件类型,从每个元素中提取对应的behavior类型,作为该属性的类型,这样xx.n1会被推导为{ loudly: () => string },xx.n2推导为{ singing: () => string }。

将IPerson改为泛型接口,是为了让它能适配不同的name字面量和behavior结构,而非固定成宽泛的索引类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:03:18