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ê quer | Escreva | Efeito em tempo de execução |
|---|---|---|
| Dizer ao compilador um tipo que você conhece | x as T | nenhum |
| Transformar uma string em número | Number(x), parseInt(x, 10) | converte |
| Transformar qualquer coisa em string | String(x), `${x}` | converte |
| Verificar o tipo antes | um type guard, typeof, instanceof | verifica |
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:
| Ferramenta | Verifica em tempo de compilação | Verifica em tempo de execução | Use quando |
|---|---|---|---|
Anotação const x: T = ... | sim, por completo | não | você mesmo monta o valor |
satisfies T | sim, por completo, e mantém o tipo inferido | não | objetos literais, configuração |
as T | só "os tipos se sobrepõem?" | não | você sabe mais que o compilador |
x! | remove só null / undefined | não | você sabe que um valor está definido |
Type guard x is T | o corpo do guard é código comum | sim | dados 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.