ProgramaciónDesarrollador Frontend

¿Cómo funcionan los modificadores de acceso (public, private, protected) en TypeScript? ¿Cuáles son las particularidades de su uso con la herencia y durante la transpileación del código a JavaScript?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En TypeScript, los modificadores de acceso se utilizan para restringir el alcance de las propiedades y métodos en las clases:

  • public — la propiedad o método está disponible en todas partes (por defecto).
  • private — disponibles solo en la clase en la que se declaran.
  • protected — disponibles en la clase y sus herederos.
class Animal { public name: string; private age: number; protected kind: string; constructor(name: string, age: number, kind: string) { this.name = name; this.age = age; this.kind = kind; } } class Dog extends Animal { bark() { console.log(this.kind); // OK: protected // console.log(this.age); // Error: private no es visible en el heredero } } const dog = new Dog('Sharik', 5, 'mamífero'); console.log(dog.name); // OK // console.log(dog.kind); // Error: protected // console.log(dog.age); // Error: private

Particularidades:

  • En el JavaScript compilado, los modificadores private y protected se implementan solo en el momento de la compilación, ¡no hay aislamiento físico en tiempo de ejecución! El código en JS contendrá todas las propiedades (por ejemplo, se pueden acceder a ellas a través de la enumeración del objeto).
  • En las nuevas versiones (desde TypeScript 3.8) se ha introducido la sintaxis para campos realmente privados: #field, pero esto ya es una especificación de JS y se compila de manera diferente.

Pregunta capciosa

Pregunta: ¿Se puede acceder a una propiedad privada de una clase TypeScript después de compilar a JavaScript?

Respuesta: Sí, ya que private (y protected) son una verificación en tiempo de compilación de TypeScript, después de la compilación a ES5 o ES6, la privacidad no se conserva, las propiedades permanecen en el objeto y son accesibles mediante el acceso por nombre de propiedad (por ejemplo, a través de object['privateProp']).

// código JS después de la compilación function Animal(name, age, kind) { this.name = name; this.age = age; this.kind = kind; } var dog = new Animal('Sharik', 5, 'mamífero'); console.log(dog['age']); // 5 — no hay acceso solo a nivel de TS!

Ejemplos de errores reales por desconocer los matices del tema.


Historia

En un gran proyecto, un desarrollador confiaba en el hecho de que los campos privados no serían accesibles en tiempo de ejecución. Como resultado, al transmitir el objeto mediante serialización (JSON.stringify) a los registros, accidentalmente se filtraron datos confidenciales, ya que la tipificación TS no protegió contra el acceso real a los campos.


Historia

En el proyecto se implementó un mecanismo de "extensión" de instancias de clases mediante la adición dinámica de propiedades. Las propiedades añadidas dinámicamente sobrescribieron los nombres privados, y su código externo las modificó accidentalmente. El error se descubrió solo en producción, y la privacidad no estaba garantizada.


Historia

Al migrar de JavaScript a TypeScript, el equipo empezó a usar protected, creyendo que esto protegía el uso de los campos fuera de las clases hijas. Pero un programador a través de Object.assign sobrescribió por error un campo protected en tiempo de ejecución y obtuvo un bug difícil de rastrear. Esto fue posible porque no había encapsulación en tiempo de ejecución.