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

Zagadnienie 6 z 12

Typy warunkowe

Typ warunkowy to `if` na poziomie typów. Zadaje zawsze to samo pytanie: czy lewa strona jest przypisywalna do prawej? Nie „czy są równe”, nie „czy to instancja” — przypisywalna, i to w jedną stronę.

Przypisywalność, nie równość

type A = 'hello' extends string ? true : false   // true
type B = string extends 'hello' ? true : false   // false
type C = never extends string ? true : false     // true — never fits anywhere
type D = { a: 1; b: 2 } extends { a: 1 } ? true : false  // true

Typ węższy jest przypisywalny do szerszego, więc test ma kierunek. Obiekt z dodatkowymi właściwościami jest przypisywalny do obiektu z mniejszą liczbą — dlatego `extends` nie sprawdzi, czy dwa typy obiektowe mają ten sam kształt.

Gdy naprawdę potrzebujesz „tego samego typu”, potrzebujesz pomocnika `Equal`, na którym oparty jest każdy test na tej stronie — dwa odroczone warunki porównywane co do tożsamości, co jest surowsze niż przypisywalność w obie strony.

Gałęzie sprawdzane są po kolei

type Describe<T> = T extends (...args: never[]) => unknown
  ? 'function'
  : T extends unknown[]
    ? 'array'
    : T extends object
      ? 'object'
      : 'primitive'

Węższe przypadki muszą iść pierwsze. Funkcje i tablice są obiektami, więc wczesne sprawdzenie `extends object` je pochłonie — to klasyczna przyczyna `DeepReadonly`, które po cichu niszczy każdą napotkaną funkcję.

Najczęstsza błędna odpowiedź

// Intent: is T exactly string?
type IsString<T> = T extends string ? true : false

IsString<'hello'>  // true — but 'hello' is not string, it is narrower
IsString<any>      // boolean — any matches both branches at once

`extends` odpowiada na „mieści się w”, więc każdy literał łańcuchowy przechodzi test na `string`. A `any` jest przypisywalne do wszystkiego, więc warunek z `any` zwraca unię obu gałęzi — wynik, o który autor prawie nigdy nie prosił.

Do zapamiętania

Warunki pytają o przypisywalność i sprawdzają gałęzie po kolei. Najpierw węższe, a po `Equal` sięgaj, gdy tylko potrzebujesz prawdziwej tożsamości.

Ćwiczone w