Cuando trabajamos con clases en TypeScript, uno de los aspectos fundamentales que debemos considerar es la visibilidad de las propiedades y métodos que definimos. Por defecto, en JavaScript todo lo que declaramos dentro de una clase es público, lo que significa que cualquier instancia puede acceder y modificar esas propiedades libremente. Esto puede ser problemático cuando queremos proteger ciertos datos internos y evitar que sean manipulados desde fuera de la clase.
Imaginemos que tenemos una clase llamada Rectángulo con dos propiedades: ancho y alto. Si no especificamos ninguna restricción, estas propiedades estarán accesibles desde cualquier parte del código. Por ejemplo, podríamos hacer algo como R1.ancho * R1.alto para calcular el área, pero también podríamos modificar directamente R1.alto, lo que puede llevar a inconsistencias o errores si no controlamos esos cambios.
Para evitar esto, TypeScript nos ofrece la palabra clave private. Al anteponer private a la declaración de una propiedad o método, indicamos que solo pueden ser accedidos desde dentro de la propia clase. Así, si declaramos:
class Rectángulo {
private ancho: number;
private alto: number;
constructor(ancho: number, alto: number) {
this.ancho = ancho;
this.alto = alto;
}
area(): number {
return this.ancho * this.alto;
}
}
Ahora, si intentamos acceder a R1.ancho o R1.alto desde fuera de la clase, TypeScript nos mostrará un error en tiempo de compilación, impidiendo que el código se ejecute con ese acceso indebido. Sin embargo, es importante entender que esta restricción es solo a nivel de compilación. Cuando TypeScript transpila a JavaScript, el código resultante no cambia en cuanto a la visibilidad, porque JavaScript no tiene una palabra clave private tradicional. Por lo tanto, en tiempo de ejecución, las propiedades siguen siendo accesibles si alguien las llama directamente.
Para abordar esta limitación, ECMAScript ha introducido un nuevo sistema para declarar propiedades privadas usando la sintaxis con una almohadilla # delante del nombre de la propiedad. Por ejemplo:
class Rectángulo {
#ancho: number;
#alto: number;
constructor(ancho: number, alto: number) {
this.#ancho = ancho;
this.#alto = alto;
}
area(): number {
return this.#ancho * this.#alto;
}
}
Este sistema es más estricto, ya que las propiedades declaradas con # son verdaderamente privadas en tiempo de ejecución y no pueden ser accedidas desde fuera de la clase, ni siquiera por accidente. Sin embargo, esta característica está todavía en fase borrador y no es oficial en todos los entornos, por lo que su soporte puede variar.
Además, la configuración del compilador de TypeScript influye en cómo se genera el código JavaScript. Si configuramos la salida para una versión antigua de ECMAScript, como ES2017 o incluso ES5, TypeScript tendrá que generar código adicional para simular el comportamiento de las propiedades privadas con #, lo que puede resultar en un código más complejo y menos eficiente. Por otro lado, si apuntamos a una versión más moderna, como ESNext, el código generado utilizará directamente la sintaxis nativa de propiedades privadas, siempre que el entorno donde se ejecute lo soporte.
Un detalle interesante es que TypeScript permite incluso transpilar a versiones muy antiguas de ECMAScript, como ES3 o ES5, que no tienen soporte nativo para clases. En esos casos, el compilador transforma las clases en funciones constructoras y utiliza prototipos para simular la herencia y las propiedades, lo que garantiza compatibilidad con navegadores antiguos como Internet Explorer 6.
En resumen, podemos controlar la visibilidad de las propiedades en nuestras clases usando private para una restricción a nivel de compilación, o el sistema de propiedades privadas con # para una privacidad real en tiempo de ejecución, siempre teniendo en cuenta la configuración de nuestro compilador y el entorno donde se ejecutará el código. Esto nos permite proteger mejor nuestros datos y mantener la integridad de nuestras clases.