Clases: modificador private

Con el modificador private podemos ocultar algunos atributos pertenecientes a una clase para que desde fuera no puedan ser vistos y modificados, facilitando así que nuestras clases sólo expongan la información que están dispuestos a exponer.

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.

Lista de reproducción
  1. 1
    Temporada 1
    5 minutos
  2. 2
    ¿Qué es TypeScript?
    11 minutos
  3. 3
    Instalando TypeScript
    8 minutos
  4. 4
    Compilando un Hola Mundo sencillo
    7 minutos
  5. 5
    Hola Mundo pero con tipos
    10 minutos
  6. 6
    Tipos: tipos primitivos
    12 minutos
  7. 7
    Tipos: tipos especiales (any, null, ...)
    10 minutos
  8. 8
    Tipos: arrays y tuplas
    11 minutos
  9. 9
    Tipos: objetos
    7 minutos
  10. 10
    Funciones: lo básico
    9 minutos
  11. 11
    Funciones: tipando funciones
    9 minutos
  12. 12
    Clases: introducción a las clases
    9 minutos
  13. 13
    Clases: creando una clase
    10 minutos
  14. 14
    Clases: modificador private
    8 minutos
  15. 15
    Clases: modificador readonly
    3 minutos
  16. 16
    Clases: Atributos virtuales con getters y setters
    10 minutos
  17. 17
    Clases: herencia
    9 minutos
  18. 18
    Clases: modificadores abstract y protected
    8 minutos
  19. 19
    Tipos alias
    6 minutos
  20. 20
    Tipos literales
    5 minutos
  21. 21
    Uniones de tipos
    7 minutos
  22. 22
    Uniones discriminantes
    7 minutos
  23. 23
    Intersecciones de tipos
    5 minutos
  24. 24
    Interfaces: introducción
    7 minutos
  25. 25
    Interfaces: modificadores y funciones
    9 minutos
  26. 26
    Interfaces: usándolas con clases
    8 minutos
  27. 27
    Interfaces: herencia de interfaces
    8 minutos
  28. 28
    Interfaces: interfaces indizadas
    5 minutos
  29. 29
    Interfaces: funciones y tipos híbridos
    5 minutos
  30. 30
    ¿Qué diferencia hay entre interfaces y tipos? (2020)
    8 minutos
  31. 31
    Casteos con as
    6 minutos
  32. 32
    instanceof y las guardas
    9 minutos
  33. 33
    Tipos enumerados
    8 minutos
  34. 34
    Valores avanzados para enumerados
    7 minutos
  35. 35
    Enumerados con valores computados
    6 minutos
  36. 36
    Genéricos en tipos
    8 minutos
  37. 37
    Múltiples genéricos y buenas prácticas
    5 minutos
  38. 38
    Genéricos en funciones
    8 minutos
  39. 39
    Genéricos con restricciones
    6 minutos
  40. 40
    Tipos de utilidad
    3 minutos
  41. 41
    Exportando módulos
    9 minutos
  42. 42
    Importando módulos
    7 minutos
  43. 43
    Export default e import asterisco
    6 minutos
  44. 44
    tsconfig
    7 minutos
  45. 45
    Módulos desde NPM
    7 minutos
  46. 46
    Arroba types y los .d.ts
    8 minutos
  47. 47
    Ejemplo (1): creando una API REST simple en TypeScript
    11 minutos
  48. 48
    Ejemplo (2): montando un servidor Express
    8 minutos
  49. 49
    Ejemplo (3): haciendo las funciones de control de datos
    11 minutos
  50. 50
    Ejemplo (4): conectando todas las piezas
    7 minutos