Médio TypeScript
Narrowing com in e instanceof
Enunciado
Crie uma hierarquia de classes Veiculo (abstrata) com subclasses Carro e Bicicleta. Cada uma tem um método específico: Carro tem abrirPortaMalas(), Bicicleta tem tocarCampainha(). Implemente uma função usarVeiculo que recebe um Veiculo e chama o método específico usando narrowing com instanceof.
Requisitos
- Usar
instanceofpara verificar o tipo concreto. - A função deve aceitar qualquer
Veiculo. - Chamar o método correto para cada subclasse.
Código inicial
abstract class Veiculo {
abstract mover(): void;
}
class Carro extends Veiculo {
mover() { console.log('Carro andando'); }
abrirPortaMalas() { console.log('Porta-malas aberto'); }
}
class Bicicleta extends Veiculo {
mover() { console.log('Bicicleta pedalando'); }
tocarCampainha() { console.log('Ring ring!'); }
}
function usarVeiculo(veiculo: Veiculo) {
// Seu código aqui
}
usarVeiculo(new Carro());
usarVeiculo(new Bicicleta());
Saída esperada
Carro andando
Porta-malas aberto
Bicicleta pedalando
Ring ring!
Ver dica
Use if (veiculo instanceof Carro) para acessar abrirPortaMalas(). Não esqueça de chamar mover() antes.
Mostrar solução
abstract class Veiculo {
abstract mover(): void;
}
class Carro extends Veiculo {
mover() { console.log('Carro andando'); }
abrirPortaMalas() { console.log('Porta-malas aberto'); }
}
class Bicicleta extends Veiculo {
mover() { console.log('Bicicleta pedalando'); }
tocarCampainha() { console.log('Ring ring!'); }
}
function usarVeiculo(veiculo: Veiculo) {
veiculo.mover(); // método comum
if (veiculo instanceof Carro) {
veiculo.abrirPortaMalas(); // veiculo é Carro
} else if (veiculo instanceof Bicicleta) {
veiculo.tocarCampainha(); // veiculo é Bicicleta
}
}
usarVeiculo(new Carro());
usarVeiculo(new Bicicleta());
Passo a passo
- Definimos a classe abstrata
Veiculocom o método abstratomover. CarroeBicicletaestendemVeiculoe implementammover, além de métodos próprios.- A função
usarVeiculorecebe umVeiculoe chamamover()(disponível em todos). - Usamos
instanceof Carropara verificar se é um carro; se sim, chamamosabrirPortaMalas(). - Caso contrário, verificamos
instanceof Bicicletae chamamostocarCampainha(). - O TypeScript estreita o tipo dentro de cada bloco.
Por que funciona
O operador instanceof verifica se o objeto é uma instância de uma classe específica, checando a cadeia de protótipos. O TypeScript reconhece essa verificação como um type guard, refinando o tipo de veiculo para a subclasse correspondente dentro do bloco.
Erros comuns
- Tentar chamar
abrirPortaMalas()fora doif:
veiculo.abrirPortaMalas(); // Erro: Property 'abrirPortaMalas' does not exist on type 'Veiculo' - Esquecer de importar ou definir as classes antes de usar.
- Usar
instanceofcom tipos que não são classes (interfaces não existem em runtime).
Outra forma de resolver
Usar uma propriedade discriminante (ex: tipo: 'carro' | 'bicicleta') e verificar com igualdade. É preferível quando não se quer depender de classes concretas ou se trabalha com objetos simples.
Saída esperada
Carro andando
Porta-malas aberto
Bicicleta pedalando
Ring ring!