Abstract Classes
TL;DR
An Abstract Class is a blueprint for other classes. You cannot create an instance of an abstract class using new. It is used to define common behavior that multiple child classes share, while forcing those child classes to implement specific missing pieces.
Mental Model
How It Works
You define an abstract class using the abstract keyword. Inside it, you can have standard, fully-implemented methods (which subclasses inherit), and you can have abstract methods (which have no body, just a signature).
Any class that extends the abstract class must provide the actual code for those abstract methods, otherwise TypeScript will throw an error.
Example
abstract class Department {
constructor(public name: string) {}
// A common method shared by all departments
printName(): void {
console.log("Department name: " + this.name);
}
// An abstract method: Forces child classes to figure this out!
abstract printMeeting(): void;
}
class AccountingDepartment extends Department {
constructor() {
super("Accounting and Auditing");
}
// We MUST implement this, or the compiler yells at us
printMeeting(): void {
console.log("The Accounting Department meets every Monday at 10am.");
}
}
// const dept = new Department("General"); // ERROR: Cannot create an instance of an abstract class.
const accounting = new AccountingDepartment();
accounting.printName();
accounting.printMeeting();
Common Interview Questions
What is the difference between an interface and an abstract class?
- An Interface is purely a compile-time concept representing a shape. It cannot contain any implementation code (logic) whatsoever. It is completely erased during compilation.
- An Abstract Class can contain actual implementation code (methods with logic) alongside abstract signatures. It compiles down to a standard JavaScript base class at runtime.
When should you use an Abstract Class?
Use them when you have a strong “is-a” relationship and want to share concrete logic across multiple related classes, but want to ensure that specific behavior is customized by the subclasses (e.g., a base DatabaseConnection class where connect() is abstract but logQuery() is shared).