首页 > 解决方案 > 访问 Typescript 对象中的动态二级属性

问题描述

我需要访问 Typescript 中的一个对象属性,其中两个级别是动态的,例如 object[key1][key2]。
即使我相信我做了适当的检查,我仍然会收到类型错误。
(object[key1] as any)[key2] 有效,但看起来不是很优雅。

有没有更好的办法?真的很感激一个想法。

在代码+操场下方。

const POIs = {
  amenity: {
    bar: {
      activity: "night",
      icon: "glass"
    }
  },
  building: {
    supermarket: {
      activiy: "day",
      icon: "warehouse"
    }
  }
}

interface noiseData {
  tags: {
    [T in keyof typeof POIs]: keyof typeof POIs[T]
  }
}


function parseNoiseSources(nss: noiseData[]): void {
  for (const ns of nss) {
    for (const category in POIs) {
      const cat = category as keyof typeof POIs
      const key = ns.tags[cat]
      if (cat in ns) {
        const obj = POIs[cat]
        if (key in obj) {
          const act = POIs[cat][key].activity
          // Below satisfies the compiler but seems redundant
          // const bct = (POIs[cat] as any)[key].activity
        }
      }
    }
  }  
}

确切的错误消息是这样的: 元素隐式具有“任何”类型,因为表达式类型为“酒吧”| "supermarket"' 不能用于索引类型 '{ bar: { activity: string; 图标:字符串;}; } | {超市:{活动:字符串;图标:字符串;}; }'。类型 '{ bar: { activity: string; 上不存在属性 'bar' 图标:字符串;}; } | {超市:{活动:字符串;图标:字符串;}; }'。

Playground: https://www.typescriptlang.org/play?#code/MYewdgzgLgBACgeQJIRgXhgbwFAxgQwFsBTMASygE8AuLXPGAI3wCdacGH9goyA3CjRgAicgHMAFlGEAaepzKgwtYWIA2+CBGHyYAX3p65eRgFcyagCZkwY9roimADsRaFWAa2JR7nPN14BIWFLfEpZXTxFcBUAd1ZiCRBTCGIdTgM8AwNsGyhXADNuYhgwEDJUgBF8KHw6PFqxCF8GAG0AFRgbGC9KEAKYKhd++GQIAF1aXpGh4hHEFA7xw2wc7ALTMB4ycBgnVlSAOXLUgGVklmBiCAAKSGbSk+Jq2tbxgEpaPnLLepgCkAsGA3JTQUqoEb3d5-PAAoEg8Bg4A1YhiQGULpgUYoaEcPyg2DI2AYImo9EEVDTAazeZjSIwAk9YgYjCQAB0jQgrSJyz8XQGIJqmPBuPpeEZIEYACt0NiuTyxfzgb1hZKpaK+ZxGQFZQt5TVxq1euM2QF+IJFXgAPRWmAAIWIahAsRgEBqFQKZGugwkJVAhCcFlcTFMsFSxEIqBYxEsm1CYCglpgNoZiNgjB4spueu5BopBDAlHeRuZJrNAioisyfmrWUMeFWQA

非常感谢您的帮助!

标签: typescripttypes

解决方案


您应该为您的 POI 对象添加类型:

interface DataFrame {
  activity: string;
  icon: string;
}
type Keys = 'amenity' | 'building'
type Data = Record<Keys, Record<string, DataFrame>>


const POIs: Data = {
  amenity: {
    bar: {
      activity: "night",
      icon: "glass"
    }
  },
  building: {
    supermarket: {
      activity: "day",
      icon: "warehouse"
    }
  }
}

interface noiseData {
  tags: {
    [T in keyof typeof POIs]: keyof typeof POIs[T]
  }
}


function parseNoiseSources(nss: noiseData[]): void {
  for (const ns of nss) {
    for (const category in POIs) {
      const cat = category as keyof typeof POIs
      const key = ns.tags[cat]
      if (cat in ns) {
        const obj = POIs[cat]
        if (key in obj) {
          const act = POIs[cat][key].activity // no error
          // Below satisfies the compiler but seems redundant
          // const bct = (POIs[cat] as any)[key].activity
        }
      }
    }
  }
}

barsupermarket对象应该有相同的类型


推荐阅读