Lições do módulo (2/2)
Sindicatos e Estreitamento
No mundo real, as variáveis e as respostas da API nem sempre têm um único tipo fixo. O TypeScript oferece Union Types para lidar com a variabilidade e Type Narrowing para operar com segurança neles em tempo de execução.
Tipos de união
Um tipo de união permite que uma variável aceite valores de tipos diferentes. É expresso usando o símbolo da barra vertical (|):
let result: number | string;
result = 42; // Valid
result = 'Error 404'; // ValidPorém, ao trabalhar com um tipo união, não podemos chamar diretamente métodos que pertencem a apenas um dos tipos (por exemplo, não podemos chamar .toUpperCase() se a variável também puder ser number). Devemos primeiro "estreitar" o tipo.
Estreitamento de tipo
Estreitamento de tipo é o processo em que o TypeScript analisa estruturas de fluxo de controle (como if ou switch) para deduzir um tipo mais específico para uma variável em tempo de execução.
Existem várias maneiras de realizar o estreitamento:
1. O Operador typeof
Ideal para distinguir tipos primitivos:
function printLength(value: string | number) {
if (typeof value === 'string') {
// TypeScript knows 'value' is a string here
console.log(value.length);
} else {
// TypeScript knows 'value' is a number here
console.log(value.toFixed(2));
}
}2. O Operador in
Usado para verificar se existe uma propriedade específica em um objeto:
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function move(animal: Fish | Bird) {
if ('swim' in animal) {
animal.swim(); // Narrowing to Fish
} else {
animal.fly(); // Narrowing to Bird
}
}Sindicatos Discriminados
O padrão Uniões Discriminadas consiste na criação de objetos que compartilham uma propriedade comum com um valor literal exclusivo (chamado de discriminador). O TypeScript reconhece esse discriminador e restringe automaticamente o tipo dentro de blocos condicionais.
interface SuccessResponse {
status: 'success'; // Literal discriminator
data: string;
}
interface ErrorResponse {
status: 'error'; // Literal discriminator
errorMessage: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
console.log('Data received:', response.data);
} else {
console.error('An error occurred:', response.errorMessage);
}
}Experimente você mesmo
Exercício 1: Tipos de união
Declare uma variável chamada id que pode ser um número ou uma string. Inicialize-o primeiro com o número 101 e, em seguida, atribua o valor da string 'USER-101'.
Mostrar dica
Use o | operador para juntar número e string na declaração da variável let.
Solução disponível após 3 tentativas
Exercício 2: Estreitamento de Tipo Básico
Crie uma função chamada formatInput que aceite uma entrada de parâmetro do tipo string ou número. Se a entrada for uma string, retorne a entrada convertida em maiúsculas. Se for um número, retorne a entrada multiplicada por 2. Especifique os tipos explicitamente.
Mostrar dica
Use typeof input === 'string' dentro de um bloco if para ramificar o comportamento.
Solução disponível após 3 tentativas
Exercício 3: Estreitando com 'in'
Dadas as duas interfaces Car (com método drive) e Boat (com método vela), escreva uma função chamada moveVehicle que aceita um parâmetro veículo do tipo Car ou Boat. Se o veículo tiver a propriedade drive, execute o método drive(). Caso contrário, execute o método Sail().
Mostrar dica
Use o operador in no formato 'dirigir' no veículo para restringir a interface.
Solução disponível após 3 tentativas
Exercício 4: Forma de União Discriminada
Defina um tipo Shape que é a união de dois tipos: Círculo e Quadrado. Círculo tem uma propriedade de tipo definida como 'círculo' (valor literal) e um raio (número). Square tem uma propriedade de tipo definida como 'quadrado' (valor literal) e um lado (número). Em seguida, escreva uma função getArea que aceite forma do tipo Shape e retorne a área como um número (para círculo Math.PI * raio * raio, para lado quadrado * lado).
Mostrar dica
Use shape.kind === 'circle' dentro de getArea para discriminar o tipo e calcular a área correta.
Solução disponível após 3 tentativas