Historia de la cuestión
En TypeScript, las propiedades privadas aparecieron inicialmente a través del modificador private, y desde ECMAScript 2021, JavaScript soporta campos verdaderamente privados mediante el símbolo #. El objetivo principal es la encapsulación de datos, para proteger los detalles internos de la clase del acceso externo.
Problema
El modificador private en TypeScript proporciona la privacidad solo en el momento de la compilación, pero en el JavaScript compilado, estos campos permanecen accesibles a través del acceso directo a las propiedades del objeto. Esto puede llevar a un cambio involuntario del estado del objeto. Los Campos Privados de ES (#) son completamente inaccesibles fuera de la clase incluso a nivel de ejecución de JS, lo que proporciona una verdadera protección de los datos.
Solución
TypeScript soporta ambos enfoques. Al elegir entre ellos, guíese por el grado necesario de protección y las limitaciones de compatibilidad con las versiones de JS.
Ejemplo de código:
class Example { private hidden: number; #trulyHidden: string; constructor() { this.hidden = 42; this.#trulyHidden = 'secret'; } getHidden() { return this.hidden; } getTrulyHidden() { return this.#trulyHidden; } } const x = new Example(); // x.hidden — error en TS, pero funcionará a través de x['hidden'] en JS // x.#trulyHidden — error de sintaxis incluso en JS
Características clave:
private garantiza la privacidad solo en la etapa de compilación de TypeScript#field proporciona una verdadera privacidad a nivel de ejecución de JavaScript# requiere soporte para JS moderno (ES2021+)¿Se puede acceder a un campo privado de una clase TypeScript a través de un acceso directo en JS?
Sí, se puede, ya que la privacidad se implementa solo en la etapa de compilación. En el JS original, el campo será una propiedad normal del objeto. Por ejemplo:
class A { private x = 1; } const a = new A(); console.log((a as any)["x"]); // 1
¿Se pueden usar campos privados con # en interfaces o describirlos usando type?
No, los campos #private son parte solo de la implementación de la clase y no pueden ser descritos en interfaces, tipos o ser usados fuera de la misma clase. Las interfaces describen solo miembros públicos.
¿Se pueden heredar campos privados declarados con #?
No, tales campos no están disponibles para las clases hijas en absoluto. Solo la clase misma tiene acceso a ellos:
class Parent { #foo = 123; } class Child extends Parent { // this.#foo = 444; // Error }
private para proteger datos críticos — conduce a vulnerabilidades por acceso directoEn un proyecto para almacenar contraseñas, se utilizó el campo private password en la clase User. Uno de los desarrolladores accidentalmente accede a través de user['password'] para depurar, y el campo es modificado por un módulo externo.
Pros:
Contras:
Un desarrollador utiliza el campo privado de ES #password. Ahora los intentos de acceder al campo a través de indexación o en herederos no tienen éxito, la seguridad de los datos está asegurada incluso al usar bibliotecas y herramientas externas.
Pros:
Contras: