liveBook · Manning

Abstract class

As explained in Essential TypeScript 5, Third Edition

An abstract class is a class that can define shared members while preventing direct instantiation and requiring derived classes to implement designated abstract members.

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

How Essential TypeScript 5, Third Edition covers it

How deep it goes
Explains declarations, inheritance, type usage, type guarding, interface reuse, generics, and the compile-time-only runtime restriction.
Examples
Uses Person, Employee, Customer, Supplier, AbstractDogOwner, and generic collection subclasses as implementation examples.
What you can do after
Build it from scratch by defining shared implementations and abstract requirements for concrete TypeScript subclasses.
How it connects
Connects abstract methods with inheritance, interfaces, generics, type unions, and instanceof-based type narrowing.

Also explained in

Compare how 6 books explain abstract class →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Essential TypeScript 5, Third Edition. The section links point to the parts of the book it draws on.