Parsa_Gholipour
Parsa_Gholipour

Reputation: 960

Typescript instantiate typeof abstract class

This is my code:

abstract class BaseClass {}
class DerivedClassA extends BaseClass {}
class DerivedClassB extends BaseClass {}
const derivedClasses: (typeof BaseClass)[] = [DerivedClassA, DerivedClassB];
for (const c of derivedClasses) {
   const instantiatedObj = new c; // error: Cannot create an instance of an abstract class
}

I have an array of derived classes which I want to iterate and initiate each. (typeof BaseClass)[] is not a suitable type. Removing it solves it. What's the correct type?

Upvotes: 1

Views: 308

Answers (2)

jcalz
jcalz

Reputation: 330216

You can use a construct signature of the form new (arg0: XXX, arg1: YYY) => ZZZ or { new (arg0: XXX, arg1: YYY): ZZZ } to represent an object that acts as a class constructor on which you can use the new operator. In the examples above, you'd pass it two arguments of type XXX and YYY and get a class instance of type ZZZ.

Since you want to call new c() with no arguments and expect the constructed instances to be assignable to BaseClass, the type you need is new () => BaseClass:

const derivedClasses: (new () => BaseClass)[] = 
  [DerivedClassA, DerivedClassB]; // okay

for (const c of derivedClasses) {
  const instantiatedObj = new c(); // okay
}

The compiler is happy to allow you to assign DerivedClassA and DerivedClassB to elements of derivedClasses because each of them can be used as a constructor that takes no arguments and produces an instance of a subtype of Baseclass. And the compiler is happy to allow you to call new c() because the construct signature takes no arguments.

Playground link to code

Upvotes: 1

Alexander Yammine
Alexander Yammine

Reputation: 558

You can do this:

abstract class BaseClass {}
class DerivedClass extends BaseClass {}
const b: BaseClass = new DerivedClass();

DerivedClass can be treated as a BaseClass given that DerivedClass as the same methods/attributes as BaseClass. And if you want to return to Derived class, you can do this:

if (b instanceof DerivedClass) {
    // use DerivedClass methods here
    b.customDerivedClassMethod()
}

Upvotes: 0

Related Questions