Uma união discriminada (etiquetada) é uma união de tipos de objeto que compartilham um campo literal comum — o discriminante — que o compilador usa para distinguir as variantes e fazer narrowing seguro.
=
| { : }
| { : ; : }
| { : ; : };
Uma união discriminada (etiquetada) é uma união de tipos de objeto que compartilham um campo literal comum — o discriminante — que o compilador usa para distinguir as variantes e fazer narrowing seguro.
=
| { : }
| { : ; : }
| { : ; : };
Cada membro tem um literal status. Verificá-lo reduz para exatamente uma variante, desbloqueando os campos dessa variante:
function render(r: Result) {
switch (r.status) {
case "loading": return "...";
case "success": return r.data; // ✅ data exists only here
case "error": return r.message; // ✅ message exists only here
}
}
Se você tentar acessar r.data no caso loading, é um erro de compilação — o sistema de tipos torna combinações inválidas irrepresentáveis.
function render2(r: Result): string {
switch (r.status) {
case "loading": return "...";
case "success": return r.data;
case "error": return r.message;
default:
const _exhaustive: never = r; // ✅ if you add a variant and forget a case, this errors
return _exhaustive;
}
}
A atribuição never força você a lidar com todos os casos — adicione um novo status e o compilador aponta cada switch que precisa ser atualizado.
Uniões discriminadas são a forma idiomática de modelar estado (loading/success/error), eventos/ações (Redux reducers) e qualquer dado "um de várias formas".
Elas tornam estados inválidos impossíveis e, com o truque never, lhe dão verificação de exaustividade em tempo de compilação — uma vitória enorme de segurança em relação à modelagem solta com boolean/campos opcionais.