Způsoby, jak TypeScript zužuje typ uvnitř větve, seskupené podle techniky: vestavěné stráže, vlastní predikáty, assertion funkce, diskriminované unie, rovnost a tok podle pravdivosti, aliasy a odložené zužování. Každý řádek spojuje techniku s jednořádkovým příkladem.
Zužování (narrowing) je způsob, jak TypeScript mění široký typ na užší uvnitř větve kódu, aby mohl dokázat, že přístup k vlastnosti je bezpečný. Každá kontrola (typeof, in, predikát, diskriminátor) říká kompilátoru: od této chvíle je hodnota konkrétnější. Techniky níže jsou pracovní sadou.
Referenční tabulka · 23 položek
Zužování typů v TypeScriptuExplained
23 of 23 rows
Vestavěné stráže
Zužuje primitivy: string, number, boolean a další.
if (typeof x === 'string') x.toUpperCase()
Zužuje na instanci třídy či konstruktabilního typu.
if (e instanceof Error) e.message
Zužuje ověřením, že vlastnost na hodnotě existuje.
if ('id' in obj) obj.id
Zužuje libovolnou hodnotu na pole; zužuje unii na jejího člena-pole.
if (Array.isArray(x)) x.map(f)
Vlastní stráže
Predikátová funkce, jejíž návratová hodnota zužuje argument.
function isUser(x): x is User { return !!x.id }
Predikát může zužovat na unii typů, ne jen na jediný typ.
function isKey(x): x is string | number
Predikát s průnikem zachovává vstupní typ a přidává k němu pole.
function hasId(x): x is x & { id: string }
Assertion funkce, která vyhodí výjimku, pokud x není daného typu.
function assertUser(x): asserts x is User
Diskriminované unie
Zužuje unii podle sdíleného literálového pole přes switch nebo if.
type E = { kind: 'a'; a: number } | { kind: 'b'; b: string }
Každý case zužuje na jednoho člena unie.
switch (u.kind) { case 'a': u.a }
Zužuje neoznačenou unii, když vlastnost existuje jen u jednoho člena.
if ('b' in u) u.b
Každý case je podmínka; vyhovující case zužuje hodnotu.
switch (true) { case typeof x === 'string': }
Výchozí case přiřazuje do never a dokazuje tak, že switch je vyčerpávající.
default: { const x: never = u }
Rovnost a tok
Odstraňuje null a undefined po kontrole rovnosti.
if (x === null) return; x.toFixed()
Odstraňuje falsy hodnoty (0, '', null, undefined, NaN).
if (!x) return; // x is defined here
Pravdivá zřetězená vlastnost dokazuje, že základní hodnota existuje.
if (user?.active) user.name
Non-null aserce odstraňuje null a undefined bez kontroly.
x!.toFixed(2)
Definite assignment: deklaruje, že x je přiřazeno před čtením.
let name!: string; init()
Zužování platí uvnitř větve a po dřívějších returnech.
if (!arr) return; arr.map(...)
Aliasy a odložené zužování
Konstantní boolean s kontrolou zužuje všude, kde se testuje.
const isStr = typeof x === 'string'; if (isStr) …
Proměnná const si zachovává zužování uvnitř closure, které ji zachytí.
const s = get(); if (s) use(() => s.length)
Od TS 5.4 si let nebo parametr zachovává zužování v closure po svém posledním přiřazení.
let n: string | null = get(); if (n) use(() => n.length)
unknown nelze použít, dokud ho stráž nezužuje na skutečný typ.