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.