Type Guarding Generic Types
O problema
import {City, Person, Product, Employee} from "./dataTypes";
let people = [new Person("Bob Smith", "London"),
new Person("Dora Peters", "New York")];
let products = [new Product("Running Shoes", 100), new Product("Hat", 25)];
let cities = [new City("London", 8136000), new City("Paris", 2141000)];
let employees = [new Employee("Bob Smith", "Sales"),
new Employee("Alice Jones", "Sales")];
class DataCollection<T> {
protected items: T[] = [];
constructor(initialItems: T[]) {
this.items.push(...initialItems);
}
filter<V extends T>(): V[] {
return this.items.filter(item => item instanceof V) as V[];
}
}
let mixedData = new DataCollection<Person | Product>([...people, ...products]);
let filteredProducts = mixedData.filter<Product>();
filteredProducts.forEach(p => console.log(`Product: ${p.name}, ${p.price}`))
Aqui, o método
filtertenta usarinstanceof V.Mas
Vé apenas um parâmetro de tipo — e parâmetros de tipo não existem em tempo de execução.O compilador remove os genéricos ao transpilar para JavaScript, então não há como usar
instanceofcomV.Resultado: erro
TS2693: 'V' only refers to a type, but is being used as a value here.
A solução em: Type Predicate
import {City, Person, Product, Employee} from "./dataTypes";
let people = [new Person("Bob Smith", "London"),
new Person("Dora Peters", "New York")];
let products = [new Product("Running Shoes", 100), new Product("Hat", 25)];
let cities = [new City("London", 8136000), new City("Paris", 2141000)];
let employees = [new Employee("Bob Smith", "Sales"),
new Employee("Alice Jones", "Sales")];
class DataCollection<T> {
protected items: T[] = [];
constructor(initialItems: T[]) {
this.items.push(...initialItems);
}
filter<V extends T>(predicate: (target) => target is V): V[] {
return this.items.filter(item => predicate(item)) as V[];
}
}
let mixedData = new DataCollection<Person | Product>([...people, ...products]);
function isProduct(target): target is Product {
return target instanceof Product;
}
let filteredProducts = mixedData.filter<Product>(isProduct);
filteredProducts.forEach(p => console.log(`Product: ${p.name}, ${p.price}`))
O que mudou:
O método
filteragora recebe uma função predicado como argumento.Essa função usa a sintaxe
target is V, que informa ao compilador que, se retornartrue, o objeto é do tipoV.Em tempo de execução, o predicado usa recursos reais do JavaScript (
instanceof Product) para verificar o tipo.Assim, o compilador entende o narrowing e o runtime consegue executar a verificação.
04 December 2025