An abstract class defines shared behavior for related classes without allowing direct instantiation. It can combine implemented methods with abstract methods that derived classes must provide. section 11.3.8
Use an abstract class when a family of classes needs a common implementation and a consistent contract:
- Declare the class with abstract class; declare required members with abstract and omit their method bodies. section 11.3.8
- Require every subclass to implement all abstract methods while inheriting regular methods from the base class. section 11.3.8
- Use derived objects through the abstract base type, accepting only the members defined by that base type until narrowing occurs. section 11.3.8
- Share part of an interface implementation and leave the remaining properties or methods abstract for subclasses. section 11.4.4
Shared details for different people
The Person class can implement getDetails once while requiring each subclass to supply getSpecificDetails. Employee can return department information, while Customer returns a credit limit. Employee, Customer, and Supplier instances can then be stored as Person values. An instanceof check can narrow a union when a class does not extend Person. section 11.3.8
Listing 11.20 Defining an abstract class in the index.ts file in the src folder
abstract class Person {
constructor(public id: string, public name: string,
public city: string) { }
getDetails(): string {
return `${this.name}, ${this.getSpecificDetails()}`;
}
abstract getSpecificDetails(): string;
}
class Employee extends Person {
constructor(public readonly id: string, public name: string,
private dept: string, public city: string) {
super(id, name, city);
}
getSpecificDetails() {
return `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);
}
getSpecificDetails() {
return `has ${this.creditLimit} limit`;
}
}
class Supplier extends Person {
constructor(public readonly id: string, public name: string,
public city: string, public companyName: string) {
super(id, name, city);
}
getSpecificDetails() {
return `works for ${this.companyName}`;
}
}
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"));
data.forEach(item => console.log(item.getDetails()));
The complete TypeScript listing shows a shared constructor and getDetails method, an abstract getSpecificDetails method, and Employee and Customer implementations. section 11.3.8
Abstract classes also work with generics. An abstract ArrayCollection<T> can implement shared storage, add, and count behavior while leaving get to ProductCollection and PersonCollection. TypeScript enforces non-instantiation and abstract-member requirements during compilation, but generated JavaScript represents the class as a regular class, so the restriction does not carry into runtime code. section 12.4.2 section 11.3.8





