Extender propiedades de clases de JavaScript en TypeScript de manera implícita
Digamos que tengo estas clases en JavaScript y estoy tratando de convertirlas a TypeScript:
class Dog {
tags = {
barked: true,
};
}
class Pug extends Dog {
tags = {
...this.tags,
snorted: true,
};
}
const pug = new Pug();
Sin embargo, el mismo código en TypeScript producirá el siguiente error:
error TS7022: 'tags' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
El error es bastante claro aquí. Estoy usando this al redefinir tags, así que TypeScript está molesto.
¿Hay alguna forma alternativa de apaciguar a TypeScript? La única forma que se me ha ocurrido hasta ahora es hacer lo que sugiere el error y escribir el tipo explícitamente. Sin embargo, en definiciones de tipo mucho más grandes se vuelve repetitivo.
Al final del día, tengo clases con propiedades que son un objeto de pares clave/valor definidos. Y cada subclase extiende el objeto de la superclase y añade pares clave/valor adicionales.
Respuesta #1
Básicamente lo tenías correcto, pero necesitas usar las etiquetas de super en lugar de las de this
class Pug extends Dog {
tags = {
...super.tags, // <-- change from 'this' to 'super'
snorted: true,
};
}
Enlace del parque
Respuesta #2
Aunque tú entiendes que la propiedad tags de Pug depende de la propiedad tags de Dog, el compilador ve tags={...this.tags} como circular, y por lo tanto no puede averiguar qué tipo va a ser. Podrías, si quieres, anotar explícitamente la propiedad tags de Pug así:
class PugExplicit extends Dog {
tags: { snorted: boolean, barked: boolean } = {
...this.tags,
snorted: true,
};
}
Pero esto es engorroso. Otra forma de proceder es afirmar que el this dentro de tu inicializador de tags es del tipo Dog y no Pug:
class Pug extends Dog {
tags = {
...(this as any as Dog).tags,
snorted: true,
};
}
Eso tiene el efecto deseado de inferir que tags de Pug es de tipo {snorted: boolean, barked: boolean} sin requerir que lo anotes explícitamente. (No estoy seguro de por qué necesitaba afirmar a través de any con this as any as Dog en lugar de simplemente this as Dog. Sin el tipo intermedio, aunque, el compilador todavía se queja de circularidad. Supongo que la identidad de this persiste a través de una afirmación pero no en dos?)
Enlace de Playground al código
