Interface Segregation Principle in TypeScript
Tags: typescript, solid
Published: 2023-04-28 09:07:09

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; 
}
```
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.'); 
    }
}
```

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')
    }
 
}
 
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkn4nn9l4rcldiqs0v5o.png)

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

- ICar interface 
- IPlane interface 

```
export interface ICar{
    drive():void;  
}

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

```
export interface IPlane{
    fly():void; 
}
```

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');
    }
}
```

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')
    }
 
}
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f8fw4skjfej4ywemiyjo.png)

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'); 
    }
 
}
```

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.