Reputation: 573
I have a RootType
like this
Type1 = {
nestedProp1: string
nestedProp2: string
}
Type2 = {
nestedProp3: string
nestedProp4: boolean
}
type RootType = {
prop1?: Type1
prop2?: Type2
}
And i'm trying to iterate through it to get all of the values like this:
const root: RootType = {
prop1: {
nestedProp1: 'foo',
nestedProp2: 'bar'
},
prop2: {
nestedProp3: 'baz',
nestedProp4: false
}
}
for(const key in root) {
for(const nestedKey in root[key as keyof RootType]) {
console.log(root[key as keyof RootType][nestedKey]) <---- how do you get the index signature type for the nested type key?
}
{
For the top level, keyof RootType
works fine for the top level keys, but i can't seem to get the nested key type. I've tried root[key as keyof RootType][nestedKey as keyof Type1 | keyof Type2]
which dosen't work, i've tried creating a new interface that extends the RootType interface with a nested index signature as a string, but typescript complains that string
isn't compatible with "prop1" | "prop2"
I'd rather not modify the RootType as it is generated off of a graphql schema, and if i change it, it'll require a custom type definition in a config file that we'll have to maintain, so a local overload would be preferable, and the best possible solution would be a clean way of getting typescript to infer the key type in a for...in loop so it dosen't have to be casted at all.
Upvotes: 1
Views: 1040
Reputation: 66103
You can use const
to store the value of the current key-value pair at each level of the for
loop, so that you can access the value in the keyof typeof <...>
declaration:
for (const key in root) {
const nestedObj = root[key as keyof typeof root];
for (const nestedKey in nestedObj) {
const nestedValue = nestedObj[nestedKey as keyof typeof nestedObj];
console.log(nestedValue);
}
}
See proof-of-concept on TypeScript Playround.
Alternatively, if you prefer to stick to your older method of referencing the type of the object directly instead of the object itself, it is possible but that also means you need to use a union type for all the nested object keys:
for (const key in root) {
const nestedObj = root[key as keyof RootType];
for (const nestedKey in nestedObj) {
// Can be very verbose, if your parent object has many nested object types
const nestedValue = nestedObj[nestedKey as keyof (Type1 | Type2)];
console.log(nestedValue);
}
}
See proof-of-concept on TypeScript Playround.
Upvotes: 1