Multiple Inheritance in TypeScript

  1. Single Inheritance in TypeScript
  2. Multiple Inheritance With TypeScript Classes
  3. Multiple Inheritance With TypeScript Interfaces
  4. Multiple Inheritance With TypeScript Mixins

There are several programming paradigms have evolved over the years. Object-Oriented Programming(OOP) is one of the main paradigms based on real-world entities and their interaction.

Inheritance is one of the well-known OOP concepts that allows acquiring the parent entity’s properties and behaviors by sub-entities.

Single Inheritance in TypeScript

TypeScript supports OOP techniques up to some extent. It supports inheriting from one parent entity, allowing programmers to reuse their code effectively.

We can inherit from a parent entity using the extends keyword, as shown in the following.

class Animal {
    constructor() {
        console.log("Animal class");
    }
}

class Cat extends Animal {

    constructor() {
        super();
    }
}

const cat = new Cat();

Output:

"Animal class"

This is called single inheritance which the given class can extend to only one parent class.

Multiple Inheritance With TypeScript Classes

It is possible to acquire properties and behaviors from more than one parent entity in Java-like languages. This is called multiple inheritance.

TypeScript does not support multiple inheritance.

Multiple Inheritance

Let’s try to extend multiple parent classes in TypeScript using extends.

class Engineer {
    constructor() {
        console.log("Employee class");
    }
}

class Person {
    constructor() {
        console.log("Person class");
    }
}

class Employee extends Engineer, Person {
}

Then, let’s transpile the TypeScript code, as shown in the following.

tsc example1.ts

Output:

TypeScript Multiple Inheritance - Output 1

As expected, it gives an error that TypeScript only allows extending a single class.

Multiple Inheritance With TypeScript Interfaces

TypeScript interfaces support multiple inheritance out of the box. They can extend more than one class.

Let’s create two classes, Person and Engineer, and add some dummy methods.

class Person {
    name: string;

    constructor() {
       console.log("Person class");
    }

    sayImAPerson(){
        console.log("Hey, I am a person");
    }
}

class Engineer {
    salary: number;
    constructor() {
        console.log("Engineer class");
    }
    sayImAnEngineer(){
        console.log("I am an engineer too");
    }
}

Next, we will be creating a new type or class to extend the above two classes.

class Employee {
    empId: string;
}

Since the Employee class cannot extend more than one parent class, we should use an interface with the same name Employee to use TypeScript declaration merging. In this way, you can merge interfaces and classes.

Let’s create the Employee interface, which extends the Person and Engineer classes, as shown in the following.

interface Employee extends Person, Engineer {
}

Let’s transpile the TypeScript code and check whether we get any errors.

Output:

TypeScript Multiple Inheritance - Output 2

As expected, there are no errors when using extends with more than one parent class inside the interface declaration. Hence, the interface supports multiple inheritances.

But there is still a problem if we call a method inside the inherited class. We do not have access to the method implementations.

Let’s try calling the sayImAnEngineer() method.

let emp: Employee = new Employee;
emp.sayImAnEngineer();

We should transpile the code first; it won’t give any error. Then, try running the generated JavaScript; it would raise an error, as shown in the following output.

Output:

TypeScript Multiple Inheritance - Output 3

TypeScript couldn’t locate the sayImAnEngineer method. We can overcome this by using TypeScript mixins.

Multiple Inheritance With TypeScript Mixins

TypeScript mixins mechanism can copy all the methods available in the parent classes to the derived class or sub-class. The mixin creation method should go through all the properties in the parent classes and retrieve the content.

Then, it should set all the content in the derived class as it is. There is a method provided by the official TypeScript documentation: mixin creation method.

It is recommended to use within your TypeScript file, as shown in the following.

function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

Let’s include the applyMixins method inside our TypeScript example.

class Person {
    name: string;

    constructor() {
       console.log("Person class");
    }

    sayImAPerson(){
        console.log("Hey, I am a person");
    }
}

class Engineer {
    salary: number;
    constructor() {
        console.log("Engineer class");
    }
    sayImAnEngineer(){
        console.log("I am an engineer too");
    }
}

class Employee {
    empId: string;
}

interface Employee extends Person, Engineer {

}

function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

Now, let’s call the applyMixins method, as shown in the following.

applyMixins(Employee, [Person, Engineer]);

The first parameter should be the derived class; in this case, it is the Employee class. The next parameter is an array that contains all the parent classes the derived class would extend.

Finally, let’s create an Employee object and call the sayImAnEngineer method from the Engineer parent class.

let emp: Employee = new Employee;
emp.sayImAnEngineer();

Output:

TypeScript Multiple Inheritance - Output 4

There are no errors this time; it means the mixins technique worked. In this way, you can implement the multiple inheritances in TypeScript.

Write for us
DelftStack articles are written by software geeks like you. If you also would like to contribute to DelftStack by writing paid articles, you can check the write for us page.