Reputation: 31982
In TypeScript, I usually define the type of a class type with:
declare type Type = {
new (...args: any[]): any
}
For example, this can used when a class is passed as an argument. This is kind-of similar to what Type
is in C#, but it can also be instantiated directly with the new
operator. AFAIK, this type definition is effectively analogous to:
A constructor function that may receive any number and type of arguments, and may return anything.
If an argument, property, or other variable is expected to contain a reference to a class (more precisely, to its constructor function), the Type
type is always at hand, and is very useful to me.
However, sometimes I come across situations where I don't have a reference to the class (constructor function) itself, only its prototype. However, it's still possible to get a reference to the class itself by
obj.constructor
Which is of type Function
however, and is not possible to instantiate as a class:
new obj.constructor(); // Error: Cannot use 'new' ...
This yields the error:
Cannot use 'new' with an expression whose type lacks a call or construct signature.
If I use type assertions, the compiler accepts the new
operator, and the compiled code behaves as expected at runtime.
Is there something I'm missing which explains why obj.constructor
is not newable off-the-shelf?
Upvotes: 1
Views: 1485
Reputation: 3968
Because TypeScript currently has no special handling for the constructor
property. It's defined in lib.d.ts for the Object interface, so it can only be generically defined as a Function.
https://github.com/Microsoft/TypeScript/issues/3841 and https://github.com/Microsoft/TypeScript/issues/4356 are the relevant issues.
You can do this:
class Foo {
constructor(public x: string) { }
}
var foo = new Foo("foo");
var bar = new (foo.constructor as { new(x: string): typeof foo })("bar");
which allows you to be generic on the type of foo
(i.e. you don't need to explicitly write Foo
in the type assertion), but you still need to write the parameters explicitly or cop out with ...args: any[]
.
Upvotes: 3