trilha

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

Buscar

Busca por título, seção e texto das notas