Skip to content

Estreitamento de Tipos em TypeScript explicados

As formas de TypeScript estreitar um tipo dentro de um ramo, agrupadas por técnica: guardas incorporados, predicados personalizados, funções de asserção, uniões discriminadas, fluxo de igualdade e verdade, e estreitamento aliased e diferido. Cada linha emparelha a técnica com um exemplo de uma linha.

Estreitar é como o TypeScript transforma um tipo largo num mais estreito dentro de um ramo de código, para provar que um acesso a propriedade é seguro. Cada verificação (typeof, in, um predicado, um discriminador) diz ao compilador: a partir daqui, o valor é mais específico. As técnicas abaixo são o conjunto de trabalho.

Tabela de referência · 23 entradas
23 of 23 rows
Guardas incorporados
Estreita primitivos: string, number, boolean e mais.if (typeof x === 'string') x.toUpperCase()
Estreita para uma instância de classe ou construtível.if (e instanceof Error) e.message
Estreita verificando que uma propriedade existe no valor.if ('id' in obj) obj.id
Estreita qualquer valor para array; estreita uma união para o seu membro array.if (Array.isArray(x)) x.map(f)
Guardas personalizados
Uma função predicado cujo retorno estreita o argumento.function isUser(x): x is User { return !!x.id }
Um predicado pode estreitar para uma união de tipos, não apenas um único.function isKey(x): x is string | number
Um predicado de interseção mantém o tipo de entrada e acrescenta-lhe campos.function hasId(x): x is x & { id: string }
Uma função de asserção que lança erro salvo se x for do tipo.function assertUser(x): asserts x is User
Uniões discriminadas
Estreita uma união por um campo literal partilhado, via switch ou if.type E = { kind: 'a'; a: number } | { kind: 'b'; b: string }
Cada case estreita para um membro da união.switch (u.kind) { case 'a': u.a }
Estreita uma união sem tag quando uma propriedade existe num só membro.if ('b' in u) u.b
Cada case é uma condição; o case correspondente estreita o valor.switch (true) { case typeof x === 'string': }
O case default atribui a never, provando que o switch é exaustivo.default: { const x: never = u }
Igualdade e fluxo
Remove null e undefined após uma verificação de igualdade.if (x === null) return; x.toFixed()
Remove valores falsy (0, '', null, undefined, NaN).if (!x) return; // x is defined here
Uma propriedade encadeada truthy prova que o valor base está presente.if (user?.active) user.name
A asserção de não-nulo remove null e undefined sem verificação.x!.toFixed(2)
Atribuição definida: declara que x é atribuído antes de ser lido.let name!: string; init()
O estreitamento aplica-se dentro do ramo e após retornos antecipados.if (!arr) return; arr.map(...)
Aliased e diferido
Um boolean const que guarda uma verificação estreita onde for testado.const isStr = typeof x === 'string'; if (isStr) …
Uma variável const mantém o seu estreitamento dentro de closures que a capturam.const s = get(); if (s) use(() => s.length)
Desde o TS 5.4, um let ou parâmetro mantém o estreitamento em closures após a sua última atribuição.let n: string | null = get(); if (n) use(() => n.length)
unknown não pode ser usado até um guarda o estreitar para um tipo real.if (typeof u === 'string') u.length