Abstraction in TypeScript
Older Article
This article was published 9 years ago. Some information may be outdated or no longer applicable.
Abstraction is an Object Oriented programming concept where a class spells out how an inherited class should implement itself, including any abstract methods.
The idea: we’re hiding the complexity of the implementation from inherited classes and letting them fill in the functionality themselves.
In TypeScript, abstraction is achieved with the abstract keyword, applied to both classes and methods.
If you’re new to TypeScript classes, read this introductory article first.
Here’s an abstract class with an abstract method:
abstract class Warrior {
readonly name: string;
public weapon: string;
constructor(name: string) {
this.name = name;
}
abstract arm(weapon: string): void;
}
Try to instantiate this class and we’ll get an error:
const john = new Warrior('John, the Nomad'); // Cannot create an instance of the abstract class 'Warrior'.
To use our abstract class, we need a subclass that extends it with the extends keyword. We also need to implement the arm() method in that subclass, otherwise TypeScript throws: Non-abstract class 'SuperWarrior' does not implement inherited abstract member 'arm' from class 'Warrior'.
class SuperWarrior extends Warrior {
constructor(name: string) {
super(name);
}
arm(weapon: string): void {
console.log(`${this.name} is a super warrior fighting with ${weapon}`);
}
}
Now we can create our warrior:
const warrior = new SuperWarrior('John, the Nomad');
warrior.arm('lance'); // John, the Nomad is a super warrior fighting with lance
Since we’re writing TypeScript, we can also bolt on Interfaces and implement them for classes. Here’s the final code:
interface IWarrior {
name: string;
weapon: string;
arm(weapon: string): void;
}
abstract class Warrior implements IWarrior {
readonly name: string;
public weapon: string;
constructor(name: string) {
this.name = name;
}
abstract arm(weapon: string): void;
}
class SuperWarrior extends Warrior {
constructor(name: string) {
super(name);
}
arm(weapon): void {
console.log(`${this.name} is a super warrior fighting with ${weapon}`);
}
}
const warrior: IWarrior = new SuperWarrior('John, the Nomad');
warrior.arm('lance');