Reputation: 31924
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.
Upvotes: 49
Views: 43060
Reputation: 20159
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!
Upvotes: 38
Reputation: 3134
Thanks to @TehauCave's answer, which was my starting point, I could figure out a way to define a type that also cares about parameter types.
export type Constructor<T, TArgs extends any[] = any> = Function & {
prototype: T,
apply: (this: any, args: TArgs) => void
};
The above type can be used either
regardless of parameter types:
Constructor<YourAbstractClass>
or
restricting parameter types:
Constructor<YourAbstractClass, [number, string, boolean]>
Using the Constructor
type, it is also possible to infer the parameter types of a given constructor:
type ConstructorParameters<T extends Constructor<any>> = T extends Constructor<any, infer TParams> ? TParams : never;
and then,
ConstructorParameters<YourAbstractClass> // e.g., [number, string, boolean]
Upvotes: 0
Reputation: 1
This solution:
type Constructor<T> = Function & { prototype: T }
won't allow you to create instances of this type using new keyword.
There's another simple solution:
type Constructor = new (...args: any[]) => AbstractClass
((Where AbstractClass
is a name of your AbstractClass))
Upvotes: 0
Reputation: 588
Was just struggling with a similar problem myself, and this seems to work for me:
type Constructor<T> = Function & { prototype: T }
Upvotes: 54
Reputation: 3826
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;
Upvotes: 3
Reputation: 164137
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;
Upvotes: 4