Menu

as em TypeScript: type assertions e casting explicados

A palavra-chave as diz ao TypeScript para tratar um valor como outro tipo. Não é um cast: nada é convertido nem verificado em tempo de execução. Veja a sintaxe com as e com sinais de menor e maior, o que o compilador permite, assertions duplas passando por unknown e quando um type guard é a ferramenta melhor.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

value as Type é uma type assertion: diz ao TypeScript para tratar value como Type. As pessoas chamam de cast, mas é só uma instrução ao compilador. Ela é apagada da saída JavaScript, não converte nada e não verifica nada em tempo de execução.

Esse é o uso típico: você sabe mais sobre um valor do que o compilador consegue saber (aqui, o formato de um JSON) e diz isso a ele. Se você estiver errado, nada avisa. As próximas seções mostram o que isso significa e quando uma verificação em tempo de execução é a escolha melhor.

as e a sintaxe com sinais de menor e maior

Existem duas grafias para a mesma assertion:

const someValue: unknown = "hello";
const a = someValue as string;   // as syntax
const b = <string>someValue;     // angle-bracket syntax, same meaning

A forma com sinais de menor e maior não é permitida em arquivos .tsx, em que <string> seria lido como uma tag JSX. Use as em todo lugar e a questão nem aparece. As assertions têm precedência baixa, então envolva-as em parênteses quando continuar a expressão: (value as string).length.

Assertions não convertem valores

Esta é a parte que causa bugs de verdade. Uma assertion muda o que o compilador acredita sobre um valor, não o valor em si:

O compilador acredita que asserted é um number, então asserted + 1 passa na verificação como aritmética. Em tempo de execução ele continua sendo a string "42", e o JavaScript concatena. Para mudar o tipo de um valor, converta-o: Number(x), String(x), Boolean(x), BigInt(x), new Date(x). A página sobre converter string para number compara as funções de conversão.

Você querEscrevaEfeito em tempo de execução
Dizer ao compilador um tipo que você conhecex as Tnenhum
Transformar uma string em númeroNumber(x), parseInt(x, 10)converte
Transformar qualquer coisa em stringString(x), `${x}`converte
Verificar o tipo antesum type guard, typeof, instanceofverifica

O que o compilador permite

O as não é ilimitado. O TypeScript permite x as T quando um tipo pode ser atribuído ao outro: ampliar ("a" as string, dog as Animal) e estreitar (animal as Dog, unknown as User) são aceitos. Quando os tipos não se sobrepõem de jeito nenhum, ele recusa:

O compilador mostra index.ts(3,11): error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. A própria mensagem indica a válvula de escape: input as unknown as number. Essa assertion dupla compila, e é tão errada em tempo de execução quanto o exemplo acima. Quando você sentir necessidade dela, a correção certa normalmente é uma conversão (Number(input)) ou um tipo diferente.

A regra de sobreposição é frouxa para objetos. Um objeto literal que tem algumas das propriedades é aceito, e é assim que o as deixa passar em silêncio objetos incompletos:

Uma anotação (const draft: User = { name: "Ada" }) ou satisfies User apontaria o email faltando (TS2741). Use as em um objeto literal só quando você realmente pretende completá-lo depois, e prefira montar o objeto completo.

as const é diferente

as const parece uma assertion, mas faz o contrário de afrouxar: torna um literal o mais estreito possível. Strings continuam literal types, arrays viram tuplas readonly e propriedades de objeto viram readonly.

Ele é seguro, porque descreve o literal exatamente, em vez de afirmar algo que o compilador não enxerga. (O sizes as readonly string[] dentro de isSize é uma assertion de ampliação, também segura: deixa o includes aceitar qualquer string.) Veja literal types para mais detalhes.

Quando um type guard é a ferramenta melhor

O as é uma afirmação; um type guard é uma verificação. Em uma fronteira em que os dados vêm de fora do seu código (JSON, fetch, localStorage, entrada do usuário, uma mensagem), a afirmação pode ser falsa, e uma assertion transforma um erro claro na fronteira em um erro confuso em outro lugar.

Um guia aproximado para as ferramentas que se parecem:

FerramentaVerifica em tempo de compilaçãoVerifica em tempo de execuçãoUse quando
Anotação const x: T = ...sim, por completonãovocê mesmo monta o valor
satisfies Tsim, por completo, e mantém o tipo inferidonãoobjetos literais, configuração
as Tsó "os tipos se sobrepõem?"nãovocê sabe mais que o compilador
x!remove só null / undefinednãovocê sabe que um valor está definido
Type guard x is To corpo do guard é código comumsimdados vindos de fora

Sobram dois bons usos para o as: estreitar algo que o compilador não consegue acompanhar (uma entrada de Map que você definiu duas linhas antes, um valor de uma biblioteca sem tipos) e código de teste que monta fixtures parciais. Mantenha-os pequenos e perto do lugar em que você sabe que a afirmação é verdadeira.

Perguntas frequentes

O que o as faz no TypeScript?

value as Type é uma type assertion: diz ao compilador para tratar value como Type dali em diante. Ela é removida do JavaScript compilado, então não faz conversão nem verificação em tempo de execução. Se a assertion estiver errada, o programa falha depois, onde quer que o tipo errado seja usado.

Como fazer cast de um tipo no TypeScript?

O TypeScript não tem casts em tempo de execução. Use as (ou o antigo <Type>value) para mudar o tipo estático quando você sabe mais que o compilador. Para converter de fato um valor, chame uma função: Number("42"), String(42), Boolean(x), new Date(text).

O que significa "as unknown as" no TypeScript?

Uma assertion dupla. O TypeScript recusa x as T quando os dois tipos não se sobrepõem de jeito nenhum (erro TS2352), e passar antes por unknown contorna essa verificação, porque qualquer coisa pode ser afirmada para unknown e a partir dele. Isso desliga por completo a verificação de tipos daquele valor, então reserve para testes e para código em que você verificou o tipo de outra forma.

Qual é a diferença entre as e os sinais de menor e maior no TypeScript?

Nenhuma no significado: <string>value e value as string são a mesma assertion. A forma com sinais de menor e maior não pode ser usada em arquivos .tsx porque conflita com o JSX, então as é a forma que todo mundo usa.

Qual é a diferença entre as e satisfies?

O as sobrescreve o tipo inferido e verifica muito pouco (propriedades faltando são aceitas). O satisfies verifica o valor contra um tipo, apontando propriedades faltando ou extras, e mantém o tipo inferido preciso. Prefira satisfies para objetos literais e as só quando você realmente sabe mais que o compilador.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR