Przejdź do treści
webtype.orgwebtype.org

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Zagadnienie 7 z 12

    infer

    infer to dopasowanie wzorca. Opisujesz oczekiwany kształt, wstawiasz infer X tam, gdzie siedzi interesujący fragment, a kompilator rozwiązuje X. Większość pomocników wyciągających z biblioteki standardowej to jeden warunek z jednym infer we właściwym miejscu.

    Prześledź typSprawdzone kompilatorem
    WyrażenieItem<string[]>
    Rozwija się dostring
    WyrażenieItem<number[]>
    Rozwija się donumber
    WyrażenieItem<boolean>
    Rozwija się donever

    Dopasuj tablicę i przechwyć typ jej elementu jako U. Typ niebędący tablicą nie pasuje do tego wzorca.

    Definicja typu
    type Item<T> = T extends (infer U)[] ? U : never

    Działa wszędzie, gdzie może pojawić się typ

    type Unwrap<T> = T extends Promise<infer Inner> ? Inner : T
    type Element<T> = T extends (infer E)[] ? E : never
    type Returns<T> = T extends (...a: never[]) => infer R ? R : never
    type Head<T> = T extends [infer H, ...unknown[]] ? H : never
    type Rest<S> = S extends `${string}-${infer R}` ? R : never

    Obietnice, tablice, zwracane typy funkcji, pozycje w krotce, wzorce łańcuchów — mechanizm jest za każdym razem ten sam. Zmienia się tylko otaczający kształt — dlatego nauka jednego uczy wszystkich.

    Ograniczanie tego, co zostaje związane

    // Without the constraint, F is unknown and cannot be
    // interpolated into a template literal.
    type First<T> = T extends [infer F extends string, ...unknown[]]
      ? `${F}!`
      : never

    infer może nieść własną klauzulę extends, która zawęża wiązanie i pozwala użyć wyniku tam, gdzie wymagany jest konkretny rodzaj typu. Bez niej często dostajesz unknown, a błąd pojawia się linijkę po przyczynie.

    Najczęstsza błędna odpowiedź

    // Intent: get the return type of any function.
    type Returns<T> = T extends () => infer R ? R : never
    
    Returns<() => string>          // string
    Returns<(a: number) => string> // never — pattern demands zero parameters
    
    // Fixed: never[] in parameter position accepts any signature,
    // because parameters are checked contravariantly.
    type Returns2<T> = T extends (...a: never[]) => infer R ? R : never

    Wzorzec musi być tak pobłażliwy jak wejścia, które chcesz dopasować. Typ funkcji bez parametrów pasuje tylko do funkcji bez parametrów, więc wszystko inne po cichu wpada w gałąź fałszywą.

    Ćwiczenie

    Wyciągnij typ elementu z typu tablicy.

    Spróbuj

    2
    • ElementOf<string[]>—
      → string
    • ElementOf<number>—
      → never

    Do zapamiętania

    Opisz kształt, zaznacz dziurę przez infer i pozwól kompilatorowi ją wypełnić. Jeśli nic nie pasuje, to wzorzec jest surowszy niż wejście — nie odwrotnie.

    Ćwiczone w