Tenho uma classe genérica que define um make
método, principalmente como uma conveniência para evitar ter que escrever new Foo()
. Funciona assim:
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"
Isso está quase certo. O tipo de instance
é a classe resolvida corretamente ( Child
), e a sugestão de tipo do IDE para os props também funciona. No entanto, a única coisa que não é feita é validar os props passados para o make
método. Como o props
parâmetro é definido como padrão para InstanceType<T>['props']
, o compilador não marcará os props ausentes como um erro. Ou seja, se eu deixasse de fora o name
prop, ele não me diria que " name
está faltando no tipo Props
". Tenho brincado com esse conceito genérico por algum tempo e não consegui descobrir como obter essa última peça do quebra-cabeça - ou mesmo se isso é possível.
Alguém tem alguma ideia de como os adereços podem ser validados corretamente?
Não misture dois parâmetros
C
para o tipo de construtor eP
para o parâmetro. Outorne o método genérico apenas sobre o tipo construtor e obtenha seu tipo de parâmetro com
ConstructorParameters
:ou (mais simples/curto e evitando a asserção de tipo) use dois tipos genéricos para o parâmetro e a instância resultante: