1

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?

12
  • Don't declare the base class abstract? The whole point of an ABC is that it isn't supposed to be instantiated. Commented Aug 12, 2022 at 12:18
  • @JaredSmith Notice a is not actually abstract. Commented Aug 12, 2022 at 12:20
  • ...but you declared a's type to be that ABC. Just don't do that. None of this makes any sense. Make it the DerivedClass, or better yet an interface that the class implements. Commented Aug 12, 2022 at 12:22
  • @JaredSmith I'm dealing with a variable which I don't know its exact type but I know it's derived from an abstract class. How can I indicate that? Commented Aug 12, 2022 at 12:24
  • 1
    Does this approach meet your needs? If so I could write up an answer; if not, what am I missing? (Please @jcalz mention me if you reply or I probably won't be notified) Commented Aug 12, 2022 at 21:50

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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()
}

5 Comments

I want to use typeof BaseClass and instantiate it.
@Parsa_Gholipour Why do you want it to be a type that by definition cannot be instantiated and then instantiate it?
@isaactfa Because I don't know its exact type. It's type of a derived class but I don't know which one.
@Parsa_Gholipour, as @isaactfa said, by definition, you cannot instantiate an abstract class. Another idea could be removing the abstract from the class definition
@AlexanderYammine Removing abstract doesn't make sense because it shouldn't be instantiable. I want to say for example a is type of one of derived classes of a base class and didn't find notations for that yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.