En Typescript, ¿por qué necesito declarar una propiedad fuera del constructor de la clase, a diferencia de Javascript donde no necesitaría hacerlo?
En Javascript podría crear una clase como la siguiente, lo que significa que no necesitaría declarar e iniciar una propiedad llamada logs fuera del constructor:
class Logger {
constructor() {
this.logs = [];
}
}
Sin embargo, en TypeScript me daría un error: Property 'logs' does not exist on type 'Logger'.ts(2339) Para solucionarlo declaré una propiedad logs así: logs: Array<any>; El pseudocódigo en TypeScript sin errores se ve así:
class Logger {
logs: Array<any>;
constructor() {
this.logs = [];
}
}
Esta probablemente sea una pregunta para principiantes de Typescript. Sin embargo, he revisado la documentación y otros recursos y no pude encontrar una explicación. Dado que sé cómo solucionarlo, me interesa más la explicación, las diferencias y las mejores prácticas.
Respuesta #1
El "por qué" es complicado. Hay dos partes en esta pregunta
1. ¿Por qué se necesita una definición de tipo?
VLAZ ya lo ha cubierto en su comentario. TypeScript no tiene suficiente información para inferir el tipo, por lo que necesita una guía más explícita.
“¡Seguramente TS puede darse cuenta de que es un arreglo!”, eso es cierto, sin embargo...
2. ¿Por qué se necesita la definición de tipo en la parte superior?
El constructor en este caso confunde las cosas, pero tomemos una clase ligeramente diferente:
class Logger {
a() {
this.logs = 1234;
}
b() {
this.logs = ['a', 'b']
}
}
A partir de lo anterior, ¿qué tipo es logs? Depende, ¿verdad? Si se llama primero a a(), entonces es un número, de lo contrario es un arreglo. "Depende" realmente no es suficiente para darnos una fuerte confianza en nuestros tipos. Entonces (creo) que TypeScript te obliga a declararlo en un lugar central: en la parte superior de la clase, fuera de cualquier método.
También podrías preguntar por qué no puede inferirlo desde el constructor. Eso siempre vendría antes de a() o b().
Sospecho que está relacionado con el hecho de que los campos pueden establecerse durante su declaración, como:
class Logger {
logs: Array<string> = ['a', 'b'];
constructor() {
this.logs = 6611; // <-- wait a second...
}
}
