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

如何在TypeScript的Map中使用自定义类对象作为键

原生Map默认采用SameValueZero算法做键匹配,对象类型的键只会匹配引用地址,无法直接指定按属性值匹配,你可以通过两种方案实现需求:

方案1:调整存储结构(简单易上手,无需额外封装)

直接将Map的键设为name字符串类型,值同时保存Foo实例和业务数据,既能通过name快速查询,也能保留完整的实例属性:

class Foo {
  name: string;
  data1: any;
  data2: any;
}

// 定义Map值的类型,同时关联Foo实例和业务数据
type MapValue<DataType> = {
  fooInstance: Foo;
  businessData: DataType;
}

// 声明Map,键为name字符串类型
const map = new Map<string, MapValue<unknown>>();

// 写入数据
const fooObject1 = new Foo();
fooObject1.name = "nameOfFooObject";
map.set(fooObject1.name, {
  fooInstance: fooObject1,
  businessData: someData
});

// 读取数据
const target = map.get("nameOfFooObject");
if (target) {
  // 可直接访问Foo实例的data1、data2属性
  console.log(target.fooInstance.data1, target.businessData);
}

方案2:封装自定义Map类(兼容原生Map用法,适合高频使用场景)

如果希望保留你示例中set传Foo实例、get传name字符串的调用方式,可以继承原生Map重写核心方法,内部自动提取name作为实际匹配键:

class FooMap<DataType> extends Map<Foo | string, DataType> {
  // 内部存储映射:name -> [Foo实例, 业务数据]
  #innerStore = new Map<string, [Foo, DataType]>();

  override get(key: Foo | string): DataType | undefined {
    const realKey = typeof key === "string" ? key : key.name;
    return this.#innerStore.get(realKey)?.[1];
  }

  override set(key: Foo, value: DataType): this {
    this.#innerStore.set(key.name, [key, value]);
    return this;
  }

  override has(key: Foo | string): boolean {
    const realKey = typeof key === "string" ? key : key.name;
    return this.#innerStore.has(realKey);
  }

  override delete(key: Foo | string): boolean {
    const realKey = typeof key === "string" ? key : key.name;
    return this.#innerStore.delete(realKey);
  }

  // 额外工具方法:直接通过name获取完整Foo实例
  getInstanceByName(name: string): Foo | undefined {
    return this.#innerStore.get(name)?.[0];
  }
}

// 用法和你的示例完全一致
const map = new FooMap<unknown>();
map.set(fooObject1, someData);
map.set(fooObject2, someData);

// 直接传name字符串取值
map.get("nameOfFooObject");
// 也可以传Foo实例取值
map.get(fooObject1);
// 直接获取Foo实例访问data属性
map.getInstanceByName("nameOfFooObject")?.data2;

注意:两种方案都默认Foo的name属性是唯一的,如果存在重名情况,需要自己添加写入校验逻辑,避免数据被覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:18:01