typescripttypescript-generics

Make static method of generic class extend parameters of resolved class


I have a generic class that defines a make method, mostly as a convenience to avoid having to write new Foo(). It works like this:

class Parent<T> {
    public declare props: T;

    constructor(props: T){
        this.props = props;
    }

    static make<T extends typeof Parent<P>, P = InstanceType<T>['props']>(this: T, props: P): InstanceType<T> {
        return new this(props) as InstanceType<T>;
    }
}

type Props = {
    name: string;
}

class Child extends Parent<Props> {
    public sayName(){
        console.log(this.props.name);
    }
}

const instance = Child.make({
    name: "Bob"
});

instance.sayName(); // "Bob"

This is almost right. The type of instance is the correct resolved class (Child), and IDE type-hinting for the props works as well. However, the only thing that doesn't get done is validating the props passed into make method. Since the props parameter is defaulted to InstanceType<T>['props'], the compiler will not mark missing props as an error. IE, if I left out the name prop, it wouldn't tell me that "name is missing on type Props". I've been playing with this generic concept for some time and I haven't been able to figure out how to get this last piece of the puzzle - or even if it is at all possible.

Does anyone have insight into how the props can be validated properly?


Solution

  • Don't mix two parameters C for the constructor type and P for the parameter. Either