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

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Zagadnienie 9 z 12

    Typy literałów szablonowych

    Typy literałów szablonowych pozwalają kompilatorowi budować i dopasowywać łańcuchy. W połączeniu z `infer` i rekurencją potrafią parsować — tak ścieżka staje się obiektem parametrów, a klucze i18n i nazwy kolumn ORM są sprawdzane w czasie kompilacji.

    Budowanie i zamiana na łańcuch

    type Greeting = `hello ${string}`
    type Event = `on${'Click' | 'Focus'}`   // 'onClick' | 'onFocus'
    type AsText = `${42}`                    // '42'
    
    // Interpolating a union multiplies out every combination.
    type Cell = `${'a' | 'b'}${1 | 2}`       // 'a1' | 'a2' | 'b1' | 'b2'

    Wstawienie unii daje iloczyn kartezjański, który rośnie szybko — TypeScript ogranicza wynik do 100 000 elementów i powyżej zgłasza błąd. Zamiana liczby na łańcuch przez `` `${N}` `` to standardowy sposób przekształcenia problemu arytmetycznego w tekstowy.

    Dopasowanie jest zakotwiczone i zachłanne od lewej

    type StartsWith<S, P extends string> = S extends `${P}${string}` ? true : false
    type EndsWith<S, P extends string> = S extends `${string}${P}` ? true : false
    type Contains<S, P extends string> = S extends `${string}${P}${string}` ? true : false
    
    // Greedy from the left: Head binds the SHORTEST prefix that works.
    type Split1<S> = S extends `${infer Head}-${infer Tail}` ? [Head, Tail] : never
    type X = Split1<'a-b-c'>   // ['a', 'b-c']

    Wzorzec musi dopasować cały łańcuch, więc miejsce, gdzie wstawisz `${string}`, jest miejscem dopuszczonego luzu. Luz z przodu znaczy „zawiera”, z tyłu — „zaczyna się od”, a po obu stronach oznacza przypadkowy test podłańcucha.

    Cztery wbudowane typy wielkości liter

    Uppercase<'abc'>      // 'ABC'
    Lowercase<'ABC'>      // 'abc'
    Capitalize<'abc'>     // 'Abc'
    Uncapitalize<'Abc'>   // 'abc'

    Te cztery są zaimplementowane natywnie w kompilatorze i nie mają źródła w TypeScripcie. Sięgaj po nie, zanim napiszesz rekurencję znak po znaku — `CamelCase` i podobne to z nimi kilka linii, a bez nich koszmar.

    Najczęstsza błędna odpowiedź

    type Replace<S extends string, From extends string, To extends string> =
      S extends `${infer H}${From}${infer T}` ? `${H}${To}${T}` : S
    
    Replace<'abc', '', 'x'>   // 'xabc' — not 'abc'

    Pusty łańcuch mieści się między dowolnymi dwoma znakami, więc pusta igła dopasowuje się natychmiast z pustym `H`. To `null` typów literałów szablonowych: pasuje wszędzie i po cichu psuje wzorce zakładające, że dopasowanie oznacza znalezienie czegoś.

    Ćwiczenie

    Zbuduj nazwę obsługi zdarzenia: `click` staje się `onClick`.

    Spróbuj

    2
    • Handler<'click'>
      'onClick'
    • Handler<'focus' | 'blur'>
      'onFocus' | 'onBlur'

    Do zapamiętania

    Wzorce są zakotwiczone po obu stronach i zachłanne od lewej. Miejsce dopuszczonego luzu decyduje, o co naprawdę pytasz, a pusty łańcuch zawsze jest przypadkiem brzegowym.

    Ćwiczone w