ค้นหาเว็บไซต์

typescript - วิธีการดึงคีย์ทั้งหมดของวัตถุซ้อนกันแบบเรียกซ้ำ?


type NestedObject = {
 amount: number,
 error: string | null,
 data: {
  rows: [],
  messages: {
   goodNews: string | null,
   badNews: string | null
  }
 }
}

//trying recursively get all keys 
type AllKeys<T, K extends keyof T> = 
 T extends object ?
  T extends infer O ? 
   {keys: K | AllKeys<O, keyof O> : never
 : K

type Test = AllKeys<NestedObject, keyof NestedObject>

เป็นผลให้ฉันมี:

type Test = { keys: 'amount' | 'error' | 'data' | ... }

แต่ฉันต้องได้:

type Test = { keys: 'amount' | 'error' | 'data' | 'rows' | 'messages' | 'goodNews' | 'badNews'}

คำตอบ #1

ดูเหมือนว่าคุณต้องการบางอย่างแบบนี้:

type RecursiveKeyof<T> = T extends object ? (
    T extends readonly any[] ? RecursiveKeyof<T[number]> : (
        keyof T | RecursiveKeyof<T[keyof T]>
    )
) : never

นี่จะเรียกซ้ำลงไปในประเภทวัตถุ ให้คุณได้คีย์ของคุณสมบัติย่อยทั้งหมดและคุณสมบัติย่อย-ย่อย เป็นต้น มันจะละเว้นค่าพื้นฐาน (ดังนั้นจึงไม่มี keyof string) และกรณีพิเศษของอาร์เรย์เพื่อให้คุณได้คีย์ของ องค์ประกอบ ของอาร์เรย์เท่านั้น ไม่ใช่อาร์เรย์เอง (ซึ่งมีคีย์เช่น number และ "push", "pop" เป็นต้น)

ดูเหมือนว่า AllKeys ของคุณต้องการคุณสมบัติ keys ดังนั้นเราจึงสามารถเขียนมันได้แบบนี้:

type AllKeys<T> = { keys: RecursiveKeyof<T> }

มาลองดูว่ามันใช้ได้ไหม:

type Test = AllKeys<NestedObject>
// type Test = {keys: "amount" | "error" | "data" | "rows" | "messages" | "goodNews" | "badNews" }

ดูดี

ลิงก์ Playground ไปยังโค้ด

คำตอบ #2

นี่ใช้ได้:

type NestedObject = {
 a: number,
 b: {
  bb: string[],
  cc: string,
  dd: {
    foo: string
    bar: {
      baz: 'qqq'
    }
  }
 }
}

type AllKeys<O extends object, K = O[keyof O]> =
  keyof O
  | (
    K extends any[]
      ? never
      : K extends object
        ? AllKeys<K>
        : never
  )

type Test = AllKeys<NestedObject>

นี่คือสนามเด็กเล่นของฉัน