DEV Community

Cover image for Abstract Classes in Typescript
Dany Paredes
Dany Paredes

Posted on • Edited on

Abstract Classes in Typescript

In Typescript the classes can inherit from another class to share methods and properties between classes also Typescript support abstract class, let me show why and when to use it.

For example, we have a base class Subscription and create the new subclass FrenchSubscription with his own sign method implementation.

class Subscription {
    url: string = "";
    constructor(public name: string) {
        this.name = name;
    }
    sign(): string {
        return "Signup!!";
    }
}

class FrenchSubscription extends  Subscription {
    url: string = "http://www.typescript.fr";
    sign(): string {
        return `Bonjour ${this.name} please go to ${this.url}`;
    }
}

Enter fullscreen mode Exit fullscreen mode

We create a new SubscriptionManager class to process a list of subscriptions and use the sign method to show a message.

The SubscriptionManager will support future subscription's child class, like EnglishSubscription class.

The SubscriptionManager has a process method to iterate over every subscription and call the sign method to show the message.

class SubscriptionManager {
    static subscriptions: Array<Subscription> = [];
    static process() {
        this.subscriptions.forEach((p) => {
            let message =  p.sign();
            console.log(message)
        })
    }
}

Enter fullscreen mode Exit fullscreen mode

The SubscriptionManager is ready to works, then add a Subscription instance to subscriptions and process it.

let france = new FrenchSubscription('Paris');
SubscriptionManager.subscriptions.push(france);

SubscriptionManager.process();
Enter fullscreen mode Exit fullscreen mode
[nodemon] starting `node Student.js`
Bonjour Paris please go to http://www.typescript.fr
Enter fullscreen mode Exit fullscreen mode

Nodemon runs the app, and perfect!! Everything works! Go to live, because my code works, but has some weaknesses.

A new developer comes to the company and needs to create a new class for English, it will inherit from the Subscription base class.
He creates EnglishSubscription and the sign method because everything looks fine IDE, and the compiler won't complain about it. Commit his changes.

class EnglishSubscription extends Subscription {
    url: string = "http://www.typescript.us";
    sign() {
        return false;
    }
}
Enter fullscreen mode Exit fullscreen mode

The service start to use the EnglishSubscription class, and it is a Subscription object will contain the sign method.

let france = new FrenchSubscription('Paris');
let ny = new EnglishSubscription('New York');

SubscriptionManager.subscriptions.push(france);
SubscriptionManager.subscriptions.push(ny)

SubscriptionManager.process();
Enter fullscreen mode Exit fullscreen mode

CRASHH!! The result is not as we expect!!!

Bonjour Paris please go to http://www.typescript.fr
false
Enter fullscreen mode Exit fullscreen mode

We had a bug and error, the method exists but doesn't fit with the initial contract and the developer doesn't know how what is the contract with the SubscriptionManager.

Sometimes we need to be sure the developer fits with the goal of the base class and be sure every child class based on it implements all members with field, methods, and signature.

Then, it is time to use the abstract class, using the abstract keyword before the method and class name them our normal class becomes to be an abstract class and every child class must implement the method with the expected signature.

Tip: The abstract methods don’t have an implementation.

abstract class Subscription {
    url: string = "";
    constructor(public name: string) {
        this.name = name;
    }
    abstract sign(): string { }
}
Enter fullscreen mode Exit fullscreen mode

The child classes from Subscription must implement the sign method with the signature, if not the IDE and compiler will raise an error.

 Property 'sign' in type 'EnglishSubscription' is not assignable to the same property in base type 'Subscription'. 
  Type '() => boolean' is not assignable to type '() => string'.     Type 'boolean' is not assignable to type 'string'.
Enter fullscreen mode Exit fullscreen mode

Using abstract the developers understand what is the goal of the base class Subscription, and his methods also we are sure for each child class
implements the methods for the proposal with an expected result but different behavior, and our code is safe and flexible.

Hopefully, that will give you a bit of help with abstract classes in Typescript. If you enjoyed this post, share it.

Photo by Karsten Winegeart on Unsplash

Top comments (0)