I need to access an object property in Typescript for which two levels are dynamic, e.g. object[key1][key2].
Even though I believe I do the appropriate checks, I still get a type error.
(object[key1] as any)[key2] works but doesn't seem very elegant.
Is there a better way? Would really appreciate an idea.
Below the code + playground.
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
}
}
}
}
}
The exact error message is this: Element implicitly has an 'any' type because expression of type '"bar" | "supermarket"' can't be used to index type '{ bar: { activity: string; icon: string; }; } | { supermarket: { activiy: string; icon: string; }; }'. Property 'bar' does not exist on type '{ bar: { activity: string; icon: string; }; } | { supermarket: { activiy: string; icon: string; }; }'.
Thanks a lot for any help!
you should add type for your POIs object:
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
}
}
}
}
}
bar
and supermarket
objects should have same types
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments