首页 > 解决方案 > how can i properly type the index signature on a nested for...in loop in typescript?

问题描述

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.

标签: typescript

解决方案


您可以使用const在循环的每一级存储当前键值对的值for,以便您可以访问keyof typeof <...>声明中的值:

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);
  }
}

请参阅 TypeScript Playround 上的概念验证

或者,如果您更喜欢直接引用对象类型而不是对象本身的旧方法,这是可能的,但这也意味着您需要对所有嵌套对象键使用联合类型:

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);
  }
}

请参阅 TypeScript Playround 上的概念验证


推荐阅读