TypeScript Interfaces Using Interfaces for Polymorphism


Example

The primary reason to use interfaces to achieve polymorphism and provide developers to implement on their own way in future by implementing interface's methods.

Suppose we have an interface and three classes:

interface Connector{
    doConnect(): boolean;
}

This is connector interface. Now we will implement that for Wifi communication.

export class WifiConnector implements Connector{

    public doConnect(): boolean{
        console.log("Connecting via wifi");
        console.log("Get password");
        console.log("Lease an IP for 24 hours");
        console.log("Connected");
        return true
    }

}

Here we have developed our concrete class named WifiConnector that has its own implementation. This is now type Connector.

Now we are creating our System that has a component Connector. This is called dependency injection.

export class System {
    constructor(private connector: Connector){ #inject Connector type
        connector.doConnect()
    }
}

constructor(private connector: Connector) this line is very important here. Connector is an interface and must have doConnect(). As Connector is an interface this class System has much more flexibility. We can pass any Type which has implemented Connector interface. In future developer achieves more flexibility. For example, now developer want to add Bluetooth Connection module:

export class BluetoothConnector implements Connector{

    public doConnect(): boolean{
        console.log("Connecting via Bluetooth");
        console.log("Pair with PIN");
        console.log("Connected");
        return true
    }

}

See that Wifi and Bluetooth have its own implementation. There own different way to connect. However, hence both have implemented Type Connector the are now Type Connector. So that we can pass any of those to System class as the constructor parameter. This is called polymorphism. The class System is now not aware of whether it is Bluetooth / Wifi even we can add another Communication module like Inferade, Bluetooth5 and whatsoever by just implementing Connector interface.

This is called Duck typing. Connector type is now dynamic as doConnect() is just a placeholder and developer implement this as his/her own.

if at constructor(private connector: WifiConnector) where WifiConnector is a concrete class what will happen? Then System class will tightly couple only with WifiConnector nothing else. Here interface solved our problem by polymorphism.