Typescript – tipos de argumentos del constructor dependiendo del tipo de propiedad de la clase
Tengo un patrón de herencia de clases donde me gustaría que el tipo del constructor de un argumento dependa del tipo de la propiedad de una clase.
Aquí está mi patrón:
class Animal{
metadata: any;
constructor(metadata){
this.metadata = metadata;
}
setMetadata(metadata: this['metadata']){
this.metadata = metadata;
}
}
class Dog extends Animal{
metadata: {
name: string,
owner: string
};
constructor(metadata){
super(metadata);
}
}
class Lion extends Animal{
metadata: {
free: boolean,
country: string
};
constructor(metadata){
super(metadata);
}
}
Imaginemos que creamos un León:
const lion = new Lion({});
La firma de lion.setMetadata
es la que espero:
(metadata: {
free: boolean;
country: string;
})=> void
y el siguiente código es un error de typescript:
lion.setMetadata({inconsistentKey : 'refused By typescript'})
Ahora me gustaría lograr el mismo comportamiento directamente con el constructor.
El siguiente código debería ser aceptado:
const lion = new Lion({free: true, country: 'somewhere'})
Pero no esto:
const lion = new Lion({})
Esto supone que el constructor de Lion infiere el tipo de sus argumentos a partir del tipo de la instancia de Lion.
Más precisamente, esperaría que lion.constructor
tenga la siguiente firma:
(metadata: {
free: boolean;
country: string;
})=> Lion
¿Hay alguna manera de lograr esto en typescript?
Porque la palabra clave this
en el tipo no está disponible para miembros estáticos de clase, por lo tanto no está disponible para el constructor.
davy.ai
Desafortunadamente, no hay una forma directa de lograr esto en TypeScript. La razón es que la función constructora es un miembro estático de la clase, y como mencionaste, la palabra clave
this
en el tipo no está disponible para miembros estáticos.Sin embargo, puedes usar una función de fábrica para lograr este comportamiento. Aquí tienes un ejemplo utilizando tu código:
Ahora puedes usar
createLion
para crear una instancia deLion
y que el tipo del argumento se infiera a partir de la propiedadmetadata
:¡Espero que esto te ayude! Déjame saber si tienes alguna otra pregunta.