DEV Community

Dhananjay Kumar
Dhananjay Kumar

Posted on

Interface Segregation Principle in TypeScript

The interface Segregation Principle is one of the fundamental principles of the SOLID principle. It says to keep the interface as small as possible. In the words of Uncle Bob, Keep interfaces small so that classes don’t end up depending on things they don’t need.

To understand the problem, say there is an interface IVehicle with two methods.

export interface IVehicle{
    drive():void; 
    fly():void; 
}
Enter fullscreen mode Exit fullscreen mode

Two classes, Car and Plane, implement the IVehicle interface. The Car class uses the interface as shown in the next code block,

import { IVehicle } from "./interface/vehicle.interface";
 
export class Car implements IVehicle{
 
    drive(): void {
        console.log('can drive');
    }
    fly(): void {
        throw new Error('Method is not implemented.'); 
    }
}
Enter fullscreen mode Exit fullscreen mode

Since a car cannot fly, the Car class is forced to implement the fly method, and for that, in the TypeScript, we are throwing an error with the message that Method is not implemented.

The Plane class uses the interface as shown in the next code block,

import { IVehicle } from "./interface/vehicle.interface";

export class Plane implements IVehicle{
 
    drive(): void {
        throw new Error("Method is not implemented.");
    }
 
    fly(): void {
        console.log('you can fly a plane')
    }
 
}

Enter fullscreen mode Exit fullscreen mode

Since a plane cannot drive, the Plane class is forced to implement the drive method, and for that, in the TypeScript, we are throwing an error with the message that Method is not implemented.
 
The above implementation violates SOLID’s ISP principle.  

Image description

To adhere to the Interface Segregation Principle, refactor the IVehicle interface in two different interfaces.

  • ICar interface
  • IPlane interface
export interface ICar{
    drive():void;  
}

Enter fullscreen mode Exit fullscreen mode

The ICar interface contains only the drive function, and the IPlane interface includes only the fly function.

export interface IPlane{
    fly():void; 
}
Enter fullscreen mode Exit fullscreen mode

The Car and Plane classes implement these two interfaces ICar and IPlane, respectively.

import { ICar } from "./interface/car.interface";
 
export class Car implements ICar{
 
    drive(): void {
        console.log('you can drive a car');
    }
}
Enter fullscreen mode Exit fullscreen mode

And the Plane class implements the IPlane interface,

import { IPlane } from "./interface/plane.interface";
 
export class Plane implements IPlane{
 
    fly(): void {
        console.log('you can fly a plane')
    }
 
}
Enter fullscreen mode Exit fullscreen mode

In this implementation,

  • Interface is small
  • The class that implements the interface is not forced to implement any method it does not need.
  • The class is not violating the Single Responsibility Principle.

After refactoring to the Interface Segregation Principle, interfaces and classes are in a one-to-one relationship and adhere to the Single Responsibility Principle.

Image description

If there is a super vehicle that flies and drives both, that can implement both interfaces.

import { ICar } from "./interface/car.interface";
import { IPlane } from "./interface/plane.interface";
 
export class SuperVehicle implements ICar,IPlane {
 
    fly(): void {
        console.log('can fly');
    }
    drive(): void {
        console.log('can drive'); 
    }
 
}
Enter fullscreen mode Exit fullscreen mode

In the above implementation,  as we have created specific interfaces, classes never implement the interfaces it does not need.
 
I strongly recommend using SOLID principles while working with TypeScript in Angular or node applications. I hope you find this post helpful. Thanks for reading.

Top comments (0)