Abstract constructor type in TypeScript
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;
John Weisz
Updated on July 09, 2022Comments
-
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 about 8 yearsUnfortunately, I need to pass an abstract class as an argument, which is possible if the parameter type is
any
orFunction
. 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 about 8 years@JohnWhite Why do you need to pass an abstract class? That's a weird scenario
-
John Weisz about 8 yearsYeah, 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 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 about 7 yearsThanks, 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 almost 6 yearsCould you please share an example of this making a class with an abstract constructor. Perhaps including extending the class?
-
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 about 4 yearsI 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 over 3 yearsAnd what is the
AbstractClass
in this context ? -
JoshuaCWebDeveloper over 2 yearsThis is now the best answer, imo.