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

TypeScript中创建Hash of Arrays(或等效结构)的最简方案

问题:在TypeScript中实现动态属性的Hash of Arrays结构

需求说明

需要创建一个Hash of Arrays(或等效数据结构),用于收集未知名称的属性(属性名作为键),每个属性对应存储一组拥有该属性的对象。核心逻辑类似以下代码,但需要在TypeScript中完成正确的类型定义与初始化,无需提前枚举所有可能的属性:

const currentProperties = currentObject.getProperties(); 
// 假设getProperties返回有效属性数组

currentProperties.forEach( (v) => {  
  HoA[ v ].push( currentObject );  
});

此前已实现过提前指定属性的场景(如下代码),但本次需要支持完全未知的属性值:

if (currentProperties.includes(Properties.exampleOne)) {
  this.exampleGroupOne.push(currentObject);
}

补充背景:处理一批拥有getProperties()方法的对象,该方法返回零个或多个属性的数组。后续需要按属性(外层循环)、对应对象(内层循环)处理数据,因此选择Hash of Arrays结构。

中间尝试的问题

以下是接近需求但存在类型错误的代码:

class Alice {
    myProps(): string[] {
        return ["Apple"];
    }
}

class Bob {
    myProps(): string[] {
        return ["Banana"];
    }
}

class Charlie {
    myProps(): string[] {
        return ["Apple", "Banana"];
    }
}

// 类型定义错误:值类型应为对象数组,而非string
const FruitBasket:{ [prop: string]: string} = {}

const myAlice = new Alice();
const myBob = new Bob();
const myCharlie = new Charlie();

const Objects = [myAlice, myBob, myCharlie];

for (const currentObject of Objects) {
    const fruits = currentObject.myProps();
    // 报错:push不存在于string类型
    fruits.forEach( (v) => { FruitBasket[v].push(currentObject);});
}

错误原因是FruitBasket的类型定义错误,将值类型设为string,但实际需要存储对象数组。

最终解决方案

通过抽象类统一对象类型、修正结构类型定义,并使用空值合并运算符初始化数组,实现需求:

abstract class JustSomeGuy {
    myProps(): string[] {
        return [];
    }
    myName(): string {
        return '';
    }
}

class Alice extends JustSomeGuy {
    myProps(): string[] {
        return ["Apple"];
    }
    myName(): string {
        return 'Alice';
    }
}

class Bob extends JustSomeGuy {
    myProps(): string[] {
        return ["Banana"];
    }
    myName(): string {
        return 'Bob';
    }
}

class Charlie extends JustSomeGuy {
    myProps(): string[] {
        return ["Apple", "Banana"];
    }
    myName(): string {
        return 'Charlie';
    }
}

// 正确定义类型:键为string,值为JustSomeGuy类型的数组
const FruitBasket:{ [prop: string]: JustSomeGuy[]} = {}

const myAlice = new Alice();
const myBob = new Bob();
const myCharlie = new Charlie();

const Objects = [myAlice, myBob, myCharlie];

// 使用??=确保属性不存在时初始化空数组,再push对象
for (const currentObject of Objects) {
    const fruits = currentObject.myProps();
    fruits.forEach( (v) => { (FruitBasket[v] ??= []).push(currentObject);});
}

// 遍历验证结果
for (let key in FruitBasket){
    let value = FruitBasket[key];
    for (let i = 0; i < value.length; i++){
        console.log("In key: " + key + " the ith element [i = " + i + "] is: " + value[i].myName() );
    }
}

关键要点

  • 用抽象类JustSomeGuy统一所有对象的类型,确保它们都实现了必要的方法
  • 正确定义FruitBasket的类型为{ [prop: string]: JustSomeGuy[] },明确每个键对应对象数组
  • 使用??=运算符(空值合并赋值),在属性首次出现时自动初始化空数组,避免Cannot read property 'push' of undefined错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:35:15