Sposoby, w jakie TypeScript zawęża typ wewnątrz gałęzi, pogrupowane według techniki: wbudowane guardy, własne predykaty, funkcje asercji, unie dyskryminowane, równość i przepływ logiczny oraz zawężanie przez aliasy i odroczone. Każdy wiersz łączy technikę z przykładem w jednej linijce.
Zawężanie (narrowing) to sposób, w jaki TypeScript zamienia szeroki typ na węższy wewnątrz gałęzi kodu, dzięki czemu może udowodnić, że dostęp do właściwości jest bezpieczny. Każde sprawdzenie (typeof, in, predykat, dyskryminator) mówi kompilatorowi: od tego miejsca wartość jest bardziej konkretna. Techniki poniżej to roboczy zestaw.
Tabela referencyjna · 23 wpisy
Zawężanie typów w TypeScriptExplained
23 of 23 rows
Wbudowane guardy
Zawęża typy proste: string, number, boolean i inne.
if (typeof x === 'string') x.toUpperCase()
Zawęża do instancji klasy lub czegoś konstruowalnego.
if (e instanceof Error) e.message
Zawęża, sprawdzając, czy właściwość istnieje na wartości.
if ('id' in obj) obj.id
Zawęża dowolną wartość do tablicy; zawęża unię do jej członka tablicowego.
if (Array.isArray(x)) x.map(f)
Własne guardy
Funkcja predykatowa, której zwracana wartość zawęża argument.
function isUser(x): x is User { return !!x.id }
Predykat może zawężać do unii typów, nie tylko do jednego.
function isKey(x): x is string | number
Predykat przecięciowy zachowuje typ wejściowy i dodaje do niego pola.
function hasId(x): x is x & { id: string }
Funkcja asercji, która rzuca wyjątek, gdy x nie jest danym typem.
function assertUser(x): asserts x is User
Unie dyskryminowane
Zawęża unię po wspólnym polu literalnym, przez switch lub if.
type E = { kind: 'a'; a: number } | { kind: 'b'; b: string }
Każdy przypadek zawęża do jednego członka unii.
switch (u.kind) { case 'a': u.a }
Zawęża unię bez tagu, gdy właściwość istnieje tylko na jednym członku.
if ('b' in u) u.b
Każdy przypadek to warunek; dopasowany przypadek zawęża wartość.
switch (true) { case typeof x === 'string': }
Gałąź default przypisuje do never, dowodząc wyczerpującej obsługi switcha.
default: { const x: never = u }
Równość i przepływ
Usuwa null i undefined po sprawdzeniu równości.
if (x === null) return; x.toFixed()
Usuwa wartości fałszywe (0, '', null, undefined, NaN).
if (!x) return; // x is defined here
Prawdziwa właściwość w łańcuchu dowodzi, że wartość bazowa istnieje.
if (user?.active) user.name
Asercja niepustości usuwa null i undefined bez sprawdzenia.
x!.toFixed(2)
Definitywne przypisanie: deklaruje, że x zostanie przypisany przed odczytem.
let name!: string; init()
Zawężanie obowiązuje wewnątrz gałęzi i po wczesnych returnach.
if (!arr) return; arr.map(...)
Aliasy i odroczenie
Stała const z wartością logiczną trzymająca sprawdzenie zawęża wszędzie tam, gdzie jest testowana.
const isStr = typeof x === 'string'; if (isStr) …
Zmienna const zachowuje swoje zawężenie w domknięciach, które ją przechwytują.
const s = get(); if (s) use(() => s.length)
Od TS 5.4 zmienna let lub parametr zachowuje zawężenie w domknięciach po ostatnim przypisaniu.
let n: string | null = get(); if (n) use(() => n.length)
unknown nie może być użyte, dopóki guard nie zawęzi go do rzeczywistego typu.