TypeScript Tipos Intermediário
Type guards
Em TypeScript, type guards são verificações que estreitam o tipo de uma variável dentro de um bloco condicional. O compilador entende typeof, instanceof, in e comparações literais como guards nativos. Para casos personalizados, criamos funções que retornam um predicado de tipo (value is T), informando ao compilador que aquele valor é do tipo T quando a função retorna true.
Além dos predicados, o TypeScript 3.7 introduziu assertion functions (asserts value is T). Elas não retornam booleano; se a função não lançar erro, o compilador assume que a condição é verdadeira e estreita o tipo dali em diante. Isso é útil para validar entradas e evitar repetição de if.
Guards reutilizáveis encapsulam lógica de verificação em um único lugar, mantendo o código DRY e seguro. Também podemos usá-los em métodos de array como filter, mas o TypeScript não infere o tipo automaticamente a partir do predicado; é preciso usar um type predicate na assinatura do callback ou uma anotação explícita.
Neste card, vamos explorar predicados x is T, assertions, guards reutilizáveis e filtros tipados com exemplos práticos.
Pontos-chave
typeof,instanceof,ine comparações literais são type guards nativos do TypeScript.- Funções com retorno
value is Tcriam predicados de tipo personalizados e reutilizáveis. asserts value is Tdeclara uma assertion function que estreita o tipo após a chamada.- Em
Array.prototype.filter, use(x): x is T => ...para que o array resultante tenha o tipo correto. - Type guards não existem em tempo de execução; são apenas para o sistema de tipos.
// Exemplo completo de type guards em TypeScript
// 1. Predicado de tipo personalizado
interface Cat {
kind: 'cat';
meow(): void;
}
interface Dog {
kind: 'dog';
bark(): void;
}
type Animal = Cat | Dog;
// Predicado: retorna true se o valor for Cat
function isCat(animal: Animal): animal is Cat {
return animal.kind === 'cat';
}
// 2. Assertion function
function assertIsCat(animal: Animal): asserts animal is Cat {
if (animal.kind !== 'cat') {
throw new Error('Não é um gato!');
}
}
// 3. Guard reutilizável para filtrar arrays
function filterCats(animals: Animal[]): Cat[] {
return animals.filter(isCat); // filter tipado com predicado
}
// Uso
const animals: Animal[] = [
{ kind: 'cat', meow: () => console.log('Miau') },
{ kind: 'dog', bark: () => console.log('Au au') },
{ kind: 'cat', meow: () => console.log('Miau') },
];
const cats = filterCats(animals);
cats.forEach(cat => cat.meow()); // OK: cats é Cat[]
// Assertion em ação
const maybeCat: Animal = { kind: 'cat', meow: () => console.log('Miau') };
assertIsCat(maybeCat);
maybeCat.meow(); // Compilador sabe que é Cat