Understanding Type Inference for Subclasses
O problema da inferência automática
Quando você cria um array com objetos de classes diferentes, o compilador não assume automaticamente que todos eles compartilham o mesmo superclasse.
Em vez disso, ele analisa os shapes (estruturas de propriedades) dos objetos e cria um union type com os tipos presentes.
class Person {
constructor(public id: string, public name: string,
public city: string) { }
}
class Employee extends Person {
constructor(public readonly id: string, public name: string,
private dept: string, public city: string) {
super(id, name, city);
}
writeDept() {
console.log(`${this.name} works in ${this.dept}`);
}
}
class Customer extends Person {
constructor(public readonly id: string, public name: string,
public city: string, public creditLimit: number) {
super(id, name, city);
}
}
class Supplier extends Person {
constructor(public readonly id: string, public name: string,
public city: string, public companyName: string) {
super(id, name, city);
}
}
let data = [new Employee("fvega", "Fidel Vega", "Sales", "Paris"),
new Customer("ajones", "Alice Jones", "London", 500)];
data.push(new Supplier("dpeters", "Dora Peters", "New York", "Acme"));
data.forEach(item => {
console.log(`Person: ${item.name}, ${item.city}`);
if (item instanceof Employee) {
item.writeDept();
} else if (item instanceof Customer) {
console.log(`Customer ${item.name} has ${item.creditLimit} limit`);
} else if (item instanceof Supplier) {
console.log(`Supplier ${item.name} works for ${item.companyName}`);
}
});
O compilador infere:
declare let data: (Employee | Customer)[];
Por que isso acontece
O compilador não “pensa em hierarquia de classes” como em C# ou Java.
Ele só vê que o array contém objetos de tipos diferentes e cria um union.
Como Employee e Customer compartilham apenas as propriedades da classe Person, o compilador considera que o array é equivalente a Person[].
Mas, como a inferência foi feita apenas com os dois primeiros elementos, o Supplier não foi incluído.
Solução: usar anotação explícita
Para indicar ao compilador que o array deve aceitar qualquer objeto que seja um Person ou uma subclasse, você precisa declarar o tipo explicitamente:
let data: Person[] = [
new Employee("fvega", "Fidel Vega", "Sales", "Paris"),
new Customer("ajones", "Alice Jones", "London", 500)
];
data.push(new Supplier("dpeters", "Dora Peters", "New York", "Acme"));
Agora o compilador entende que o array pode conter Employee, Customer, Supplier ou qualquer outra subclasse de Person.
26 November 2025