Curriculum
Course: TypeScript
Login
Text lesson

Inheritance: Extends

Classes can extend one another using the extends keyword. However, a class can extend only one other class.

Example

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }
}

class Square extends Rectangle {
  public constructor(width: number) {
    super(width, width);
  }

  // getArea gets inherited from Rectangle
}

Override

When a class extends another class, it can replace members of the parent class with the same name.

In newer versions of TypeScript, this can be explicitly marked using the override keyword.

Example

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  // using protected for these members allows access from classes that extend from this class, such as Square
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }

  public toString(): string {
    return `Rectangle[width=${this.width}, height=${this.height}]`;
  }
}

class Square extends Rectangle {
  public constructor(width: number) {
    super(width, width);
  }

  // this toString replaces the toString from Rectangle
  public override toString(): string {
    return `Square[width=${this.width}]`;
  }
}
By default, the override keyword is optional when overriding a method, but it helps prevent accidentally overriding a non-existent method. To enforce its usage when overriding, use the noImplicitOverride setting.

Abstract Classes

Classes can be designed to serve as base classes for other classes without requiring all members to be implemented by using the abstract keyword. Members that are not implemented in the base class are also marked with the abstract keyword.

Example

abstract class Polygon {
  public abstract getArea(): number;

  public toString(): string {
    return `Polygon[area=${this.getArea()}]`;
  }
}

class Rectangle extends Polygon {
  public constructor(protected readonly width: number, protected readonly height: number) {
    super();
  }

  public getArea(): number {
    return this.width * this.height;
  }
}

Abstract classes cannot be instantiated directly because they lack implementations for all their members.