代码之家  ›  专栏  ›  技术社区  ›  David Alvarez

高级打字脚本:查找嵌套对象中键“id”的所有值

  •  0
  • David Alvarez  · 技术社区  · 1 年前

    我试图提取对象中第一层和所有嵌套层的键“id”的所有值。

    鉴于我 ExampleType ,我想 NestedID<ExampleType> 成为 "one" | "two" | "three" | "four" 然而,我做错了什么,这只会让我 "one" 我不明白为什么。

    有人明白为什么这行不通吗?

    我的灵感来自 https://dev.to/pffigueiredo/typescript-utility-keyof-nested-object-2pa3 这是一个非常好的教程。

    type ExampleType = {
      id: "one"
      children: [{ id: "two" }, { id: "three"; children: [{ id: "four" }] }, { abc: "def" }]
      efg: "hij"
    }
    
    type NestedId<ObjectType extends Record<string, any> | undefined> = {
      [Key in keyof ObjectType & string]: ObjectType[Key] extends undefined
        ? never
        : Key extends "id" // if the key is "id"
          ? ObjectType[Key] // return the value of the key
          : Key extends "children" // else, if the key is "children"
            ? ObjectType[Key] extends Array<Record<string, any> | undefined> // and its value is an array of object
              ? NestedId<ObjectType[Key][number]> // recursive call
              : never // else, children value is not an object --> return never
            : never // else, key is not "id" or "children" --> return never
    }[keyof ObjectType & string]
    
    const id1: NestedId<ExampleType> = "one" // works as expected
    const id2: NestedId<ExampleType> = "two" // doesn't work (Type "two" is not assignable to type "one")
    const id3: NestedId<ExampleType> = "three" // doesn't work (Type "three" is not assignable to type "one")
    const id4: NestedId<ExampleType> = "four" // doesn't work (Type "four" is not assignable to type "one")
    const foo: NestedId<ExampleType> = "foo" // works as expected
    const bar: NestedId<ExampleType> = "bar" // works as expected
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   braza    1 年前

    您可以使用 infer 为了实现这一目标。它获取父id,并递归检查子props,以便从那里添加id(如果存在的话)。

    type NestedId<ObjectType> = 
      ObjectType extends { id: infer IdType } 
        ? IdType | (ObjectType extends { children: Array<infer ChildType> } 
          ? NestedId<ChildType> 
          : never) 
        : never;
    

    在这个例子中,你会得到 "one" | "two" | "three" | "four" 回来,其他一切都像 "foo" 将出错。