如何在打字稿中的嵌套for ... in循环中正确键入索引签名?

时间:2020-04-02 19:16:13

标签: typescript

我有一个RootType这样的人

Type1 = {
 nestedProp1: string
 nestedProp2: string
}

Type2 = {
 nestedProp3: string
 nestedProp4: boolean
}

type RootType = {
  prop1?: Type1
  prop2?: Type2
}

我正在尝试遍历它以获取所有像这样的值:

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?
  }
{

对于顶层,keyof RootType对于顶层键工作正常,但是我似乎无法获得嵌套键类型。我尝试过root[key as keyof RootType][nestedKey as keyof Type1 | keyof Type2]无效,我尝试过创建一个新接口来扩展RootType接口,并将嵌套索引签名作为字符串扩展,但是打字稿抱怨string不兼容与"prop1" | "prop2"

我不想修改RootType,因为它是从graphql模式生成的,如果我更改它,它将需要在配置文件中需要自定义类型定义,因此我们必须维护该定义,因此本地重载是更可取的,最好的解决方案是使打字稿以for ... in循环推断键类型的一种干净方法,从而根本不必强制转换。

1 个答案:

答案 0 :(得分:1)

您可以使用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);
  }
}

See proof-of-concept on TypeScript Playround

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

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