Tecnologias/01 - Linguagens/02 - TypeScript2 min
Unions, Narrowing e Valores Ausentes
Union
Uma união representa alternativas: string | number aceita um texto ou um número.
Enquanto a alternativa concreta é desconhecida, só operações válidas para as
possibilidades restantes são permitidas.
Narrowing
Narrowing é o refinamento do tipo a partir do fluxo do programa. Verificações com
typeof, comparações de valores e testes de propriedades dão evidências ao compilador.
Uma união discriminada usa uma propriedade comum com valores literais diferentes.
type Resultado =
| { ok: true; total: number }
| { ok: false; motivo: string };
function apresentar(resultado: Resultado): string {
if (resultado.ok) {
return `Total: ${resultado.total}`;
}
return resultado.motivo;
}
console.log(apresentar({ ok: true, total: 30 }));
Dentro do if, ok: true identifica a alternativa com total. Fora desse caminho,
o retorno anterior deixa apenas a alternativa com motivo.
Referência: Narrowing.
Ausência de valor
Com strictNullChecks, string | undefined exige tratar a ausência antes de usar
operações que dependem de um texto. ?. interrompe o acesso quando a base é null ou
undefined; ?? fornece um substituto apenas para esses dois valores.
function rotulo(nome?: string): string {
return nome?.trim() ?? "sem nome";
}
console.log(rotulo()); // sem nome
console.log(rotulo("")); // texto vazio
A string vazia não aciona ??. Isso difere de ||, que também trata "", 0 e false
como motivos para usar o valor alternativo.
Asserções
valor! e valor as Tipo alteram o que o compilador aceita sem acrescentar uma
verificação de execução. Se a suposição estiver errada, o acesso ainda pode falhar.
Referências: tipos e asserções e nullish coalescing.
Aprofundamento aplicado
Estados válidos por construção
Um pedido com pago: boolean e comprovante?: string permite combinações ambíguas.
Uma união discriminada liga o comprovante ao estado correto:
type Pagamento =
| { estado: "pendente" }
| { estado: "confirmado"; comprovante: string }
| { estado: "recusado"; motivo: string };
function descrever(p: Pagamento): string {
switch (p.estado) {
case "pendente": return "Aguardando";
case "confirmado": return p.comprovante;
case "recusado": return p.motivo;
default: {
const impossivel: never = p;
return impossivel;
}
}
}
O never exige que todas as alternativas tenham sido tratadas. Se um novo estado
for acrescentado ao tipo, o compilador aponta os locais que precisam decidir seu significado.
Isso ajuda a evoluir máquinas de estado; a validação de um JSON externo continua necessária.
Referência: exaustividade.
Exercício: acrescente o estado estornado, com data do estorno.
Resultado esperado: a função deixa de compilar até o novo caso ser tratado;
um pagamento pendente não exige comprovante fictício.
Relacionado: 8. Validação de Dados em TypeScript.
Parte de TypeScript