Aprenda / TypeScript do zero

FundamentosAula 4 de 1415 min0% da trilha

Funções tipadas e union types

Tipar parâmetro e retorno de função, e o 'narrowing' que o TS faz sozinho dentro de um if.

Tipando parâmetro e retorno

function somar(a: number, b: number): number {
  return a + b;
}

// o tipo de retorno geralmente é inferido, mas escrevê-lo documenta a intenção
// e o TS avisa se o corpo da função não bater com o que foi prometido:
function dividir(a: number, b: number): number {
  if (b === 0) return "erro"; // Error: Type 'string' is not assignable to type 'number'.
  return a / b;
}

Union type — "isso ou aquilo"

function formatarId(id: string | number): string {
  return `ID-${id}`;
}

formatarId(42);     // ok
formatarId("42");   // ok
formatarId(true);   // Error: Argument of type 'boolean' is not assignable...

Narrowing — o TS "estreita" o tipo dentro de um if

Quando uma variável é string | number, você não pode chamar direto um método específico de string (o TS não sabe qual dos dois é, em tempo de compilação). Mas dentro de um if que testa o tipo, o TS "lembra" da checagem:

function formatar(valor: string | number) {
  if (typeof valor === "string") {
    return valor.toUpperCase(); // aqui dentro, TS sabe que valor é string
  }
  return valor.toFixed(2); // aqui, só sobra number — TS sabe por eliminação
}

Isso se chama narrowing: o tipo vai "estreitando" conforme o código faz checagens — sem você precisar de nenhuma anotação extra dentro do if, o TS já entende sozinho.

Discriminated union — o padrão pra "isso é uma coisa OU outra, com formatos diferentes"

type Resultado =
  | { sucesso: true; dado: string }
  | { sucesso: false; erro: string };

function tratar(resultado: Resultado) {
  if (resultado.sucesso) {
    console.log(resultado.dado); // TS sabe que "dado" existe aqui
  } else {
    console.log(resultado.erro); // e que "erro" existe só aqui
  }
}

O campo sucesso (o "discriminante") é o que permite o TS saber, dentro de cada branch, qual dos dois formatos está em jogo — muito parecido com o padrão ServiceResult que aparece no Padrão API.

Exercício

Escreva uma função descrever(valor: string | string[]) que retorna o próprio valor se for string, ou os valores unidos por vírgula se for array.

Quiz rápido

O que é 'narrowing' em TypeScript?
Num type Resultado = { sucesso: true; dado: string } | { sucesso: false; erro: string }, qual o papel do campo sucesso?