O tipo possível muda ao longo do caminho
Uma união indica alternativas, não a soma de todas as propriedades disponíveis. Para usar uma operação, o verificador precisa de saber que ela existe em cada possibilidade ainda presente naquele ponto. typeof value === "string" pode excluir number e justificar uma chamada de toUpperCase no ramo correspondente.
Esse conhecimento não é um carimbo permanente na variável. Uma atribuição posterior pode mudar o tipo observado, desde que o novo valor seja compatível com o contrato declarado. Ao ler um excerto, marca a condição que foi tomada, as saídas antecipadas e as atribuições seguintes. O método permitido depende da situação atual do fluxo.
Saídas antecipadas e ausência
Uma função que devolve imediatamente quando x é null deixa apenas os outros membros da união nos caminhos que continuam. A saída não transforma null numa string; impede que esse caso chegue à chamada seguinte. Esta distinção ajuda a interpretar funções com vários motivos de rejeição.
O JavaScript mantém particularidades que o modelo de tipos respeita. typeof null é "object", pelo que esse teste não basta para distinguir um array de null. Uma condição de veracidade exclui null, mas também exclui uma string vazia ou zero. A guarda deve refletir os valores que o contrato aceita, em vez de procurar apenas uma forma curta de remover um aviso.
Ligar variantes aos dados que exigem
Um único objeto com status: "ok" | "error" e campos opcionais value e message admite combinações incompletas. Testar status não torna automaticamente value obrigatório. O verificador não deduz relações de negócio que o tipo não declarou.
Uma união de objetos separados pode dizer que o estado ok tem value obrigatório e o estado error tem message obrigatório. O discriminante comum, com literais distintos, seleciona a forma relevante. Isso melhora a leitura dos consumidores e expõe construções internas incompletas. Continua a ser uma representação estática: uma resposta de rede precisa de validação antes de receber este contrato.
Exaustividade revela decisões por tomar
Depois de tratar todos os membros de uma união discriminada, o caminho restante pode ter tipo never. Atribuir a variável a uma constante explicitamente never exige que nada previsto no modelo tenha ficado por tratar. Se uma extensão acrescentar pending sem alterar o switch, o novo membro torna-se visível como erro de atribuição.
Substituir a atribuição por as never muda a função da linha: passa a afirmar a impossibilidade em vez de a exigir. Um default que devolve sucesso também pode ocultar estados novos. O objetivo é obrigar a uma decisão explícita sobre cada variante, sem confundir essa verificação com um validador dos dados que chegam de fora.
Predicados são contratos a rever
Uma função com retorno x is string informa o verificador de como refinar x quando o resultado é true. A assinatura pode ser útil para centralizar verificações repetidas. Contudo, a declaração não é uma demonstração lógica de que o corpo implementa todas as condições necessárias.
Um predicado que devolve sempre true pode convencer o consumidor a chamar um método de string sobre um número. A revisão deve comparar o tipo prometido com cada caminho de aceitação e de rejeição. Também deve perguntar se a função prova apenas uma propriedade superficial ou todo o contrato anunciado. Não se atribui confiança a dados externos só porque a assinatura usa a sintaxe de predicado.
Leitura guiada de uma decisão de entrega
O exemplo descreve três estados já validados na fronteira: accepted inclui receipt, rejected inclui reason e pending inclui requestId. Cada ramo lê apenas o campo garantido pela variante. Não é preciso usar ! porque o modelo representa a relação entre estado e dados. A função só produz texto; não executa uma entrega nem altera uma decisão remota.
Imagina agora uma variante cancelled com um motivo. Identifica que linha denuncia a extensão incompleta e que ramo precisa de ser acrescentado. Se um chamador não tipado enviar um estado desconhecido, o throw do default pode atuar como defesa, mas não confirma que os campos das variantes conhecidas tenham sido validados corretamente.
Escolher a correção que conserva informação
Quando surge um diagnóstico, compara as alternativas pelo contrato que deixam ao consumidor. Acrescentar uma guarda pode preservar um valor válido; redesenhar uma união pode tornar uma relação explícita; tratar um estado novo pode evitar uma conclusão incorreta. any, ! e assertions podem remover o aviso sem fornecer nenhuma dessas propriedades.
Nos casos desta aula, os dados do briefing são factos e restrições, e a resposta exige escolher uma revisão justificada. Distingue uma falha do modelo de uma falha de validação externa. Um modelo mais preciso melhora a análise estática, mas não comprova por si só a correção de todos os produtores nem o resultado operacional de uma ação.
// TypeScript 7.0; strict: true; received state already validated.
type Delivery =
| { status: "accepted"; receipt: string }
| { status: "rejected"; reason: string }
| { status: "pending"; requestId: string };
function describe(result: Delivery): string {
switch (result.status) {
case "accepted": return "Receipt: " + result.receipt;
case "rejected": return "Rejected: " + result.reason;
case "pending": return "Pending: " + result.requestId;
default: {
const remaining: never = result;
throw new Error("Unexpected delivery state");
}
}
}Segue cada ramo do switch. O modelo liga estado a campos obrigatórios. A variável remaining serve de controlo estático; o throw é uma defesa separada em execução e não substitui validação à entrada. Não é necessário executar o excerto.
Armadilhas comuns
Confundir campos opcionais com variantes; esquecer null depois de typeof object; confiar num predicado sem verificar o corpo; substituir a atribuição a never por uma assertion.
Tópicos relacionados: Tipos estáticos e valores em execução · Funções e contratos de chamada · Dados externos e fronteiras de erro
O refinamento acompanha evidência e caminhos. Um bom modelo torna explícitas as relações que os consumidores precisam de usar.
Referência: TypeScript Handbook: Narrowing · TypeScript 7.0; explicit strict and host configuration