Przejdź do treści
webtype.orgwebtype.orgDwanaście zagadnień · 11/12

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Zagadnienie 11 z 12

    Krotki wariadyczne

    Krotki to jedyna struktura danych na poziomie typów, która ma długość — a więc jedyny licznik. Każda arytmetyka na typach, jaką zobaczysz, to przebrane liczenie elementów krotki.

    Rozwinięcia łączą

    type A = [1, 2]
    type B = [3, 4]
    type Joined = [...A, ...B]        // [1, 2, 3, 4]
    type Prefixed = [0, ...A]         // [0, 1, 2]
    
    type Len = Joined['length']       // 4  — a numeric literal type

    Dla krotki o stałej długości `length` jest literałem liczbowym, a nie `number`. Ten jeden fakt umożliwia arytmetykę: zbuduj krotkę odpowiedniego rozmiaru, a potem odczytaj jej długość.

    Dodawanie to złączenie, odejmowanie to dopasowanie

    type Build<N extends number, Acc extends unknown[] = []> =
      Acc['length'] extends N ? Acc : Build<N, [...Acc, unknown]>
    
    type Add<A extends number, B extends number> =
      [...Build<A>, ...Build<B>]['length']
    
    type Sub<A extends number, B extends number> =
      Build<A> extends [...Build<B>, ...infer Rest] ? Rest['length'] : never

    Budowanie krotki dodaje; rozkładanie odejmuje. Akumulator trzyma `unknown`, bo zawartość nie ma znaczenia — to zbiór kresek, a nie kolekcja czegokolwiek.

    Element rest nie musi być ostatni

    type Last<T> = T extends readonly [...unknown[], infer L] ? L : never
    type Init<T> = T extends readonly [...infer I, unknown] ? I : never

    Wzorzec krotki może zawierać dokładnie jeden element rest i wolno mu stać na początku. Tak dociera się do końca krotki bez liczenia.

    Najczęstsza błędna odpowiedź

    // Intent: subtract.
    type Sub<A extends number, B extends number> =
      [...Build<A>, ...Build<B>]['length']
    // That is addition with a different name — concatenating
    // can only ever make the tuple longer.

    Odejmowanie musi krotkę rozłożyć, czyli wymaga dopasowania wzorca, a nie budowania. Jeśli Twój typ arytmetyczny tylko rozwija, potrafi tylko dodawać.

    Ćwiczenie

    Dodaj element na początek krotki.

    Spróbuj

    2
    • Unshift<[2, 3], 1>
      [1, 2, 3]
    • Unshift<[], 'a'>
      ['a']

    Do zapamiętania

    Długość krotki to jedyna liczba, którą system typów potrafi liczyć. Buduj, by dodać, rozkładaj, by odjąć, i spodziewaj się limitu rekurencji w okolicach tysiąca.

    Ćwiczone w