Da trilha de TypeScript Este conceito ainda não saiu como card do dia. ir para o card de hoje

TypeScript Tipos Intermediário

Narrowing

Narrowing (estreitamento de tipos) é o processo pelo qual o TypeScript refina o tipo de uma variável dentro de um bloco de código, com base em verificações feitas em tempo de execução. Isso permite acessar propriedades e métodos específicos de um tipo sem precisar de casts manuais, mantendo a segurança de tipos.

O compilador usa análise de fluxo para acompanhar como o tipo de uma variável muda ao longo do código. Verificações como typeof, instanceof, o operador in, comparações de igualdade e até mesmo asserções de tipo influenciam esse fluxo. Por exemplo, dentro de um if (typeof x === 'string'), o TypeScript sabe que x é string naquele bloco.

Além disso, o narrowing funciona com uniões discriminadas, onde uma propriedade literal comum (como kind) permite distinguir entre variantes de um tipo. Isso é muito usado em padrões de projeto como Redux actions ou resultados de API.

Neste card, vamos explorar os principais mecanismos de narrowing e como aplicá-los para escrever código mais seguro e expressivo.

Pontos-chave

  • typeof estreita tipos primitivos como string, number, boolean, symbol, bigint, undefined, object e function.
  • instanceof estreita para instâncias de classes, verificando o protótipo.
  • O operador in verifica se uma propriedade existe em um objeto, estreitando uniões de tipos de objeto.
  • Comparações de igualdade (===, !==) com literais ou outros valores podem estreitar o tipo.
  • A análise de fluxo do TypeScript rastreia o tipo ao longo do código, inclusive após retornos e em blocos condicionais.
narrowing.ts
// Exemplo de narrowing com typeof, instanceof, in e igualdade

class Cachorro {
  latir() { return 'Woof!'; }
}

class Gato {
  miar() { return 'Miau!'; }
}

type Animal = Cachorro | Gato;

function emitirSom(animal: Animal): string {
  if (animal instanceof Cachorro) {
    return animal.latir(); // animal é Cachorro
  } else {
    return animal.miar(); // animal é Gato
  }
}

// Narrowing com typeof
function formatar(valor: string | number): string {
  if (typeof valor === 'string') {
    return valor.toUpperCase();
  }
  return valor.toFixed(2);
}

// Narrowing com in
interface Peixe { nadar(): void }
interface Passaro { voar(): void }

function mover(animal: Peixe | Passaro) {
  if ('nadar' in animal) {
    animal.nadar();
  } else {
    animal.voar();
  }
}

// Narrowing com igualdade
type Status = 'ativo' | 'inativo';
function mostrarStatus(s: Status) {
  if (s === 'ativo') {
    console.log('Usuário ativo');
  } else {
    console.log('Usuário inativo');
  }
}

// Testando
console.log(emitirSom(new Cachorro())); // Woof!
console.log(formatar(42)); // 42.00
console.log(formatar('typescript')); // TYPESCRIPT
mover({ nadar: () => console.log('Nadando') }); // Nadando
mostrarStatus('ativo'); // Usuário ativo

Exercícios

  1. 1
    Fácil

    Narrowing com typeof

    Escreva uma função formatarValor que recebe um parâmetro valor do tipo string | number. Se for string, retorne a string em maiúsculas; se for number, retorne o número com duas casas decimais como string.

    Resolver
  2. 2
    Médio

    Narrowing com in e instanceof

    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.

    Resolver
  3. 3
    Desafio

    Narrowing com união discriminada e análise de fluxo

    Defina uma união discriminada Resultado que representa o resultado de uma operação: { sucesso: true, valor: number } ou { sucesso: false, erro: string }. Implemente uma função processar que recebe um Resultado e retorna uma string descritiva. Use narrowing por igualdade na propriedade sucesso. Além disso, trate o caso em que a entrada pode ser null ou undefined usando narrowing com typeof ou verificação de nulidade.

    Resolver

Continue estudando