Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: instance of an abstract class

Tags:

typescript

Ok. this is very simple, just to remove an annoying error message.

I have an abstract class Router:

export abstract class Router {
}

And an interface like this

interface IModule {
    name: string;
    forms: Array<IForm>,
    route: typeof Router
}

Now I have a class which looks like this, and many others based on Router abstract

export class Module1 extends Router {
}

Now, I want to instantiate the route like this:

let module: IModule = { 
    name: "My Module",
    forms: [],
    route: Module1
}

let router = new module.route(); 
// TS2511: Cannot create an instance of an abstract class.

The code run just fine, and the instance of router = new Module1() is made properly, but I obviously doesn't write it properly in Typescript because I see TS2511: Cannot create an instance of an abstract class. when transpiling.

What is the correct way to define this?

Thank you

like image 729
Magician Avatar asked Sep 16 '18 20:09

Magician


People also ask

How do I create an instance of an abstract class in TypeScript?

We cannot create an instance of an abstract class. An abstract class typically includes one or more abstract methods or property declarations. The class which extends the abstract class must define all the abstract methods.

Can we have abstract class in TypeScript?

Implementation of Abstract Classes in TypeScript The function Object() { [native code] } declares the firstName and lastName attributes in the Employee class. The method getStipend() is an abstract method. The logic will be implemented in the derived class based on the employee type.

What is the purpose of abstract class in TypeScript?

Object-oriented programs contain concretions and abstractions. Abstract classes are one of two ways we can implement abstractions in object-oriented programming. Use abstract classes to define shared behavior or implement the Template Method pattern.

What is instance in TypeScript?

TypeScript defines a constructor using the constructor keyword. A constructor is a function and hence can be parameterized. The this keyword refers to the current instance of the class. Here, the parameter name and the name of the class's field are the same.


2 Answers

When you have an abstract class, it's constructor is only invokable from a derived class, since the class is abstract and should not be instantiated. This carries over when you type something as typeof AbstractClass, the constructor will not be callable.

The solution would to be to not use typeof Router but rather a constructor signature that returns a Router

interface IModule {
    name: string;
    forms: Array<IForm>,
    route: new () => Router
}

Another solution if you need to access static methods of Router is to create an interface derived from typeof Router which will erase the abstractness of the constructor:

export abstract class Router {
    static m(): void { console.log("Router"); }
}
type RouterClass = typeof Router;
interface RouterDerived extends RouterClass { }

interface IModule {
    name: string;
    route: RouterDerived
}

export class Module1 extends Router {
    static m(): void { console.log("Module1"); }
}

let module: IModule = { 
    name: "My Module",
    route: Module1
}

module.route.m();
let router = new module.route(); 
like image 51
Titian Cernicova-Dragomir Avatar answered Sep 19 '22 14:09

Titian Cernicova-Dragomir


Note, second part of the accepted answer covers:

if you need to access static methods of Router ...

The proposed solution doesn't actually work. Just spent fair bit of time trying to figure this out so though I'd add: the way to do this is:

type RouterDerived = {new (): Router} & typeof Router;

Full example playground.

like image 44
spinkus Avatar answered Sep 19 '22 14:09

spinkus