Przejdź do treści
webtype.orgwebtype.org

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Zagadnienie 3 z 12

    keyof i dostęp indeksowany

    Te dwa operatory pozwalają rozłożyć typ obiektowy. keyof daje klucze, dostęp indeksowany zwraca typ wartości. Prawie każde użyteczne przekształcenie w tej ścieżce to te dwa połączone z czymś, co iteruje.

    Prześledź typSprawdzone kompilatorem
    Wyrażeniekeyof User
    Rozwija się do"name" | "age"
    WyrażenieUser["name"]
    Rozwija się dostring
    WyrażenieUser[keyof User]
    Rozwija się dostring | number

    Odczytaj klucze, a potem typ wartości. Odczyt wszystkich kluczy daje unię typów wartości.

    Definicja typu
    type User = { name: string; age: number }

    keyof daje unię, nie listę

    interface User { id: number; name: string }
    
    type Keys = keyof User        // 'id' | 'name'
    type Values = User[keyof User] // number | string

    Wynikiem jest unia literałów kluczy, w nieokreślonej kolejności. Nie da się zapytać o „pierwszy klucz” — kolejność nie należy do tego, co gwarantuje typ obiektowy, a poleganie na niej byłoby poleganiem na szczególe implementacji.

    Indeksowanie unią się rozdziela

    interface User { id: number; name: string; admin: boolean }
    
    type One = User['id']              // number
    type Some = User['id' | 'name']    // number | string
    type Every = User[keyof User]      // number | string | boolean
    
    type Element = string[][number]    // string

    Indeksowanie unią kluczy daje unię odpowiadających typów wartości. T[number] na tablicy lub krotce to ta sama idea i sposób, by w jednym kroku zamienić krotkę w unię.

    Najczęstsza błędna odpowiedź

    interface User { id: number; name: string }
    
    // Intent: the value types of User.
    type Values = keyof User[]
    // Actually parses as keyof (User[]) — the keys of an ARRAY:
    // 'length' | 'push' | 'pop' | ...
    
    type Fixed = User[keyof User]  // number | string

    Przyrostkowe [] wiąże silniej niż keyof, więc to pyta o klucze tablicy użytkowników, a nie o wartości użytkownika. Wynikiem jest wielka unia nazw metod tablicy, która psuje się potem daleko od prawdziwego błędu.

    Ćwiczenie

    Utwórz unię wszystkich typów wartości w T.

    Spróbuj

    1
    type User = { id: number; name: string }
    • Values<User>—
      → string | number

    Do zapamiętania

    keyof T otwiera obiekt, a T[K] z niego czyta. Sięgaj po nie, zanim napiszesz typ rekurencyjny — zaskakująco wiele problemów nie potrzebuje niczego więcej.