Abstract constructor type in TypeScript

28,531

Solution 1

Was just struggling with a similar problem myself, and this seems to work for me:

type Constructor<T> = Function & { prototype: T }

Solution 2

As of TypeScript 4.2, you can use an abstract constructor type:

abstract class Utilities {
    abstract doSomething(): void;
}

type ConstructorFunction = abstract new (...args: any[]) => any;
var UtilityClass: ConstructorFunction = Utilities; // ok!

Solution 3

Having the same problem. I guess, an essence of abstract class constructor signature is an absense of new ( ... ) : X thingy in its declaration. That's why it can be declared explicitly.

However. You can do this, and it will compile.

var UtilityClass: typeof Utilities  = Utilities;

typeof Something is a nice way to reference constructor types, however, it cannot be extended.

And in any case you can do thing like this:

var UtilityClass: ConstructorFunction = <any> Utilities;

Solution 4

The whole point with abstract classes (in OO in general) is that you can not instantiate them, you need a concrete non-abstract implementation.

I assume that you want to have different implementations to that abstract class and want to be able to receive one of those implementations (as a parameter or something of the likes).
If that's the case, then maybe this might solve your problem:

declare type ConstructorFunction<T extends Utilities> = new (...args: any[]) => T;

abstract class Utilities { }

class MyUtilities extends Utilities { }

var UtilityClass: ConstructorFunction<MyUtilities> = MyUtilities; 
Share:
28,531
John Weisz
Author by

John Weisz

Updated on July 09, 2022

Comments

  • John Weisz
    John Weisz almost 2 years

    The type signature for a non-abstract class (non-abstract constructor function) in TypeScript is the following:

    declare type ConstructorFunction = new (...args: any[]) => any;
    

    This is also called a newable type. However, I need a type signature for an abstract class (abstract constructor function). I understand it can be defined as having the type Function, but that is way too broad. Isn't there a more precise alternative?


    Edit:

    To clarify what I mean, the following little snippet demonstrates the difference between an abstract constructor and a non-abstract constructor:

    declare type ConstructorFunction = new (...args: any[]) => any;
    
    abstract class Utilities {
        ...
    }
    
    var UtilityClass: ConstructorFunction = Utilities; // Error.
    

    Type 'typeof Utilities' is not assignable to type 'new (...args: any[]) => any'.

    Cannot assign an abstract constructor type to a non-abstract constructor type.

  • John Weisz
    John Weisz about 8 years
    Unfortunately, I need to pass an abstract class as an argument, which is possible if the parameter type is any or Function. However, these types allow objects other than abstract classes to be passed as well, hence my need for a type definition especially for abstract classes.
  • Nitzan Tomer
    Nitzan Tomer about 8 years
    @JohnWhite Why do you need to pass an abstract class? That's a weird scenario
  • John Weisz
    John Weisz about 8 years
    Yeah, it is. It's for a custom serialization/deserialization engine where it's possible to annotate properties with decorators. Member polymorhpism is supported, and therefore an abstract class can be specified for a property type, which is then passed into a metadata structure. Runtime type checks are in place currently, but it would be significantly better with type-safety.
  • Nitzan Tomer
    Nitzan Tomer about 8 years
    @JohnWhite if I get you right then you only need that abstract class to get metadata from it. If that's the case then just get it as any because I don't see the benefits of having the class type. Unless I'm missing something, if that's the case then you probably should explain the scenario better to get real help.
  • Knaģis
    Knaģis about 7 years
    Thanks, this does exactly what is needed. @cheez - This describes a Function with a prototype - so instead of requiring that the type defines a constructor, this defines that it defines the prototype. Which is what an abstract class is - no constructor, just the prototype.
  • Seph Reed
    Seph Reed almost 6 years
    Could you please share an example of this making a class with an abstract constructor. Perhaps including extending the class?
  • Seph Reed
    Seph Reed over 5 years
    @Knagis could one of you please elaborate on this answer. I'd really like to be able to use it, but the way it's shown above is not a complete enough answer for me to understand.
  • Griffork
    Griffork about 4 years
    I know this is old but I'm running into the same issue, I'm using polymorphism to store the child classes of a certain class in a map, but can't instantiate them because the parent is marked as abstract. I'd like type-safety on the constructor arguments as the spec is still in flux but can't have it because the compiler errors.
  • Angelin Calu
    Angelin Calu over 3 years
    And what is the AbstractClass in this context ?
  • JoshuaCWebDeveloper
    JoshuaCWebDeveloper over 2 years
    This is now the best answer, imo.