Skip to content

Type-indsnævring i TypeScript forklaret

De måder, TypeScript indsnævrer en type inde i en gren, grupperet efter teknik: indbyggede vagter, egne prædikater, assertion-funktioner, diskriminerede unions, ligheds- og sandhedskontrol samt aliaser og udskudt indsnævring. Hver række parrer teknikken med et eksempel på én linje.

Indsnævring er, hvordan TypeScript omdanner en bred type til en snævrere inde i en kodegren, så den kan bevise, at en egenskabsadgang er sikker. Hver kontrol (typeof, in, et prædikat, en diskriminator) fortæller compileren: herfra er værdien mere specifik. Teknikkerne nedenfor er arbejdssættet.

Referencetabel · 23 poster
23 of 23 rows
Indbyggede vagter
Indsnævrer primitiver: string, number, boolean og flere.if (typeof x === 'string') x.toUpperCase()
Indsnævrer til en instans af en klasse eller en konstruerbar type.if (e instanceof Error) e.message
Indsnævrer ved at tjekke, at en egenskab findes på værdien.if ('id' in obj) obj.id
Indsnævrer enhver værdi til et array; indsnævrer en union til dens array-medlem.if (Array.isArray(x)) x.map(f)
Egne vagter
En prædikatfunktion, hvis returværdi indsnævrer argumentet.function isUser(x): x is User { return !!x.id }
Et prædikat kan indsnævre til en union af typer, ikke kun til en enkelt.function isKey(x): x is string | number
Et snit-prædikat bevarer inputtypen og tilføjer felter til den.function hasId(x): x is x & { id: string }
En assertion-funktion, der kaster, medmindre x er typen.function assertUser(x): asserts x is User
Diskriminerede unions
Indsnævrer en union via et fælles literalfelt med switch eller if.type E = { kind: 'a'; a: number } | { kind: 'b'; b: string }
Hver case indsnævrer til ét medlem af unionen.switch (u.kind) { case 'a': u.a }
Indsnævrer en umarkeret union, når en egenskab kun findes på ét medlem.if ('b' in u) u.b
Hver case er en betingelse; den matchende case indsnævrer værdien.switch (true) { case typeof x === 'string': }
Default-caset tildeler til never og beviser, at switchen er udtømmende.default: { const x: never = u }
Lighed og kontrolflow
Fjerner null og undefined efter en lighedstjek.if (x === null) return; x.toFixed()
Fjerner falsy-værdier (0, '', null, undefined, NaN).if (!x) return; // x is defined here
En sand kædet egenskab beviser, at basisværdien er til stede.if (user?.active) user.name
Non-null-assertionen fjerner null og undefined uden et tjek.x!.toFixed(2)
Definite assignment: erklærer, at x tildeles en værdi, før den læses.let name!: string; init()
Indsnævring gælder inde i grenen og efter tidlige returns.if (!arr) return; arr.map(...)
Aliaser og udskudt indsnævring
En const-boolesk værdi med et tjek indsnævrer, hvor den end testes.const isStr = typeof x === 'string'; if (isStr) …
En const-variabel bevarer sin indsnævring i closures, der fanger den.const s = get(); if (s) use(() => s.length)
Siden TS 5.4 bevarer et let eller en parameter indsnævring i closures efter sin sidste tildeling.let n: string | null = get(); if (n) use(() => n.length)
unknown kan ikke bruges, før en vagt indsnævrer den til en rigtig type.if (typeof u === 'string') u.length