I want to make a Constructor type that takes a class as a type parameter and returns the signature of its constructor.
This would be useful in defining a static property make method on a class that can create an instance of that class rather than creating it with a new ClassInstance(...) statement.
This is what I've got so far:
type ClassConstructorArgs<T> = T extends { new (...args: infer A): any }
? A
: never;
type Constructor<T> = (...args: ClassConstructorArgs<T>) => T;
class Person {
constructor(public name: string, public age: number) {}
static make: Constructor<typeof Person> = (...args) => new Person(...args);
// ^^^^^^^^^^^^^^^^^^^
// Type 'Person' is missing the following properties from type 'typeof Person': prototype, make
}
The problem is that the static make has an error: Type 'Person' is missing the following properties from type 'typeof Person': prototype, make
I understand that this is because my Constructor type is wrong, constructors of class T don't return the class T itself but an instance of T.
But then I don't know how I can express that Constructor returns an instance of T rather than the class T itself. Is that even possible in TypeScript?
Typescript has builtin utilities both for ConstructorParameters and InstanceType:
type Constructor<T extends new (...args: any) => any> =
(...args: ConstructorParameters<T>) => InstanceType<T>;
class Person {
constructor(public name: string, public age: number) {}
static make: Constructor<typeof Person> = (...args) => new Person(...args);
}
const p = Person.make('some name', 1); // p is of type Person
Playground
If you wonder how these utilities are defined and what's wrong with your attempt, here you go:
type ConstructorParameters<T extends new (...args: any) => any> =
T extends new (...args: infer P) => any ? P : never;
type InstanceType<T extends new (...args: any) => any> =
T extends new (...args: any) => infer R ? R : any;
Source
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With