Restrição pelo Discriminante
Permita que o TypeScript restrinja variantes em instruções switch.
Restrição pelo Discriminante é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 4 aulas no total.
Refinamento pelo discriminante
Depois de verificar o discriminante, TypeScript refina a união para o membro correspondente e disponibiliza seus campos específicos. Esse é o benefício principal do padrão.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape) {
if (s.kind === "circle") return Math.PI * s.radius ** 2;
return s.side ** 2;
}
console.log(area({ kind: "circle", radius: 2 }).toFixed(2));Seleção pelo discriminante
Uma seleção switch sobre o discriminante é a maneira mais clara de tratar cada variante. Dentro de cada case, o tipo é refinado automaticamente.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
}
}
console.log(area({ kind: "square", side: 5 }));Campos específicos de cada membro em cada caso
No caso "circle", s.radius está disponível, mas s.side não está. TypeScript sabe exatamente em qual membro você está.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function describe(s: Shape) {
switch (s.kind) {
case "circle": return "r=" + s.radius;
case "square": return "side=" + s.side;
}
}
console.log(describe({ kind: "circle", radius: 9 }));Refinamento baseado em condições
Você não precisa usar uma seleção. Uma simples condição if que compare o discriminante produz um refinamento igualmente eficaz.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function perimeter(s: Shape): number {
if (s.kind === "circle") {
return 2 * Math.PI * s.radius;
}
return 4 * s.side;
}
console.log(perimeter({ kind: "square", side: 3 }));O acesso ao campo errado falha
Antes do refinamento, você não pode acessar um campo específico de um membro. TypeScript informa um erro porque a propriedade não existe em todos os membros.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function broken(s: Shape) {
// Error: radius does not exist on Square
// return s.radius;
return s.kind;
}
console.log(broken({ kind: "square", side: 1 }));Refinamento com discriminantes booleanos
Para uma união { ok: true } | { ok: false }, verificar if (r.ok) refina o tipo para o membro de sucesso.
type Result =
| { ok: true; data: string }
| { ok: false; error: string };
function handle(r: Result): string {
if (r.ok) return "Data: " + r.data;
return "Error: " + r.error;
}
console.log(handle({ ok: false, error: "boom" }));Refinamento por retorno antecipado
Retornar antecipadamente para uma variante refina o restante do código para as outras variantes, uma maneira organizada de tratar os casos um por vez.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function label(s: Shape): string {
if (s.kind === "circle") return "circle";
// s is now narrowed to Square here
return "square with side " + s.side;
}
console.log(label({ kind: "square", side: 8 }));Combinação com outras condições
Você pode combinar a verificação do discriminante com outras lógicas. TypeScript mantém o refinamento enquanto a condição do discriminante for verdadeira nesse ramo.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function bigCircle(s: Shape): boolean {
return s.kind === "circle" && s.radius > 100;
}
console.log(bigCircle({ kind: "circle", radius: 150 }));Refinamento em filtros de matrizes
O refinamento também funciona dentro de funções de retorno. Aqui cada forma é verificada individualmente à medida que iteramos.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
const shapes: Shape[] = [
{ kind: "circle", radius: 1 },
{ kind: "square", side: 2 }
];
shapes.forEach(s => {
if (s.kind === "circle") console.log("c", s.radius);
else console.log("s", s.side);
});Retornos de seleções permanecem seguros quanto aos tipos
Quando uma seleção trata todos os casos e retorna um valor, TypeScript infere um tipo de retorno preciso a partir da união de todos os resultados dos casos.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function tag(s: Shape) {
switch (s.kind) {
case "circle": return s.radius;
case "square": return s.side;
}
}
console.log(tag({ kind: "circle", radius: 4 }));Reunindo o refinamento
Seja usando switch ou if, é a verificação do discriminante que torna o acesso aos campos dos membros seguro. Em seguida, vamos garantir que todos os casos sejam tratados.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
return s.kind === "circle" ? Math.PI * s.radius ** 2 : s.side ** 2;
}
console.log(Math.round(area({ kind: "circle", radius: 10 })));Verificação rápida: refinamento
Teste sua compreensão do refinamento por discriminantes.
Recapitulação: refinamento pelo discriminante
Você viu que verificar o discriminante com switch ou if refina a união para um único membro, expondo apenas os campos específicos desse membro. Retornos antecipados e condições combinadas também preservam o refinamento.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
const s: Shape = { kind: "square", side: 7 };
console.log(s.kind === "square" ? s.side : 0);Perguntas Frequentes
A aula “Restrição pelo Discriminante” é grátis?
Sim — o texto completo de “Restrição pelo Discriminante” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 4 aulas no total.
O que vou aprender em “Restrição pelo Discriminante”?
Permita que o TypeScript restrinja variantes em instruções switch. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar TypeScript Academy?
Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Restrição pelo Discriminante”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de TypeScript Academy?
Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Construindo Uniões Discriminadas
- Restrição pelo Discriminante
- Verificação de Exaustividade com never
- Modelando Máquinas de Estado