Lección 95: Clases y Modificadores en TypeScript
🎯 Objetivo: Aprender a usar clases en TypeScript con tipado estático, modificadores de acceso y parameter properties.
1. Clases con tipos
Section titled “1. Clases con tipos”TypeScript extiende las clases de JavaScript añadiendo anotaciones de tipos en propiedades y métodos.
💻 Ejemplo
class Usuario { nombre: string; email: string; edad: number;
constructor(nombre: string, email: string, edad: number) { this.nombre = nombre; this.email = email; this.edad = edad; }
saludar(): string { return `Hola, soy ${this.nombre}`; }}
const user = new Usuario("Ana", "ana@mail.com", 30);console.log(user.saludar()); // "Hola, soy Ana"Inicialización estricta
Section titled “Inicialización estricta”TypeScript exige que las propiedades estén inicializadas en el constructor o con un valor por defecto.
class Producto { nombre: string; precio!: number; // ! asigna definitivamente (assertion) categoria: string = "general"; // valor por defecto
constructor(nombre: string) { this.nombre = nombre; }}⚠️ El operador ! (definite assignment assertion) le dice a TypeScript “confía en mí, se asignará antes de usarse”. Úsalo con cuidado.
2. Modificadores de acceso
Section titled “2. Modificadores de acceso”| Modificador | Acceso desde |
|---|---|
public | Cualquier lugar (por defecto) |
private | Solo dentro de la clase |
protected | Dentro de la clase y subclases |
private
Section titled “private”class CuentaBancaria { private saldo: number;
constructor(saldoInicial: number) { this.saldo = saldoInicial; }
depositar(cantidad: number): void { this.saldo += cantidad; }
obtenerSaldo(): number { return this.saldo; }}
const cuenta = new CuentaBancaria(1000);cuenta.depositar(500);console.log(cuenta.obtenerSaldo()); // 1500// cuenta.saldo; // ❌ Error: propiedad privada🧠 Diferencia con JS #: private de TS es solo en tiempo de compilación, no en ejecución. # de JS (campos privados reales) sí protege en runtime.
protected
Section titled “protected”class Empleado { protected salarioBase: number = 1000; public nombre: string;
constructor(nombre: string) { this.nombre = nombre; }}
class Desarrollador extends Empleado { calcularSalario(): number { return this.salarioBase * 1.5; // ✅ acceso a protected }}
const dev = new Desarrollador("Carlos");// dev.salarioBase; // ❌ Error: no accesible fuera de la clase3. readonly en propiedades
Section titled “3. readonly en propiedades”readonly evita que una propiedad sea modificada después de la inicialización.
class Configuracion { readonly version: string; readonly creadoEn: Date = new Date();
constructor(version: string) { this.version = version; }}
const config = new Configuracion("v2.0");// config.version = "v3.0"; // ❌ Error: readonly
// Puede combinarse con modificadores:class Usuario { public readonly id: number; private readonly token: string;
constructor(id: number, token: string) { this.id = id; this.token = token; }}4. Parameter Properties
Section titled “4. Parameter Properties”TypeScript ofrece una sintaxis compacta para declarar e inicializar propiedades directamente en el constructor.
// Versión tradicionalclass UsuarioTradicional { public nombre: string; public email: string; private edad: number;
constructor(nombre: string, email: string, edad: number) { this.nombre = nombre; this.email = email; this.edad = edad; }}
// Versión con parameter properties ✨class UsuarioCompacto { constructor( public nombre: string, public email: string, private edad: number ) {}}
// Ambas son equivalentesconst u = new UsuarioCompacto("Ana", "ana@mail.com", 30);console.log(u.nombre); // ✅ accesible// console.log(u.edad); // ❌ privadoPuedes combinar con readonly:
class Articulo { constructor( public readonly id: string, public titulo: string, private _contenido: string ) {}}5. implements para verificar interfaz
Section titled “5. implements para verificar interfaz”La palabra clave implements verifica que una clase cumpla con una interfaz.
interface IRepositorio { guardar(datos: unknown): void; obtener(id: string): unknown; eliminar(id: string): void;}
class RepositorioUsuarios implements IRepositorio { guardar(datos: unknown): void { console.log("Guardando..."); }
obtener(id: string): unknown { return { id, nombre: "Usuario" }; }
eliminar(id: string): void { console.log(`Eliminando ${id}`); }}
// ❌ Si falta un método, TypeScript lo señalaclass RepositorioIncompleto implements IRepositorio { guardar(datos: unknown): void {} // ❌ Faltan obtener y eliminar}implements múltiple
Section titled “implements múltiple”interface Versiones { version: string; mostrarVersion(): void;}
interface Backup { respaldar(): void; restaurar(): void;}
class Servicio implements Versiones, Backup { version: string = "1.0";
mostrarVersion(): void { console.log(this.version); }
respaldar(): void { console.log("Respaldo realizado"); }
restaurar(): void { console.log("Restauración completada"); }}6. Getters y Setters
Section titled “6. Getters y Setters”class Temperatura { private _celsius: number = 0;
get celsius(): number { return this._celsius; }
set celsius(valor: number) { if (valor < -273.15) { throw new Error("Temperatura por debajo del cero absoluto"); } this._celsius = valor; }
get fahrenheit(): number { return (this._celsius * 9) / 5 + 32; }}
const temp = new Temperatura();temp.celsius = 25;console.log(temp.fahrenheit); // 77// temp.celsius = -300; // ❌ Error en runtime7. Propiedades y métodos estáticos
Section titled “7. Propiedades y métodos estáticos”class Utilidades { static readonly PI: number = 3.1416;
static formatearFecha(fecha: Date): string { return fecha.toISOString().split("T")[0]; }
static crearId(): string { return Math.random().toString(36).substring(2, 9); }}
console.log(Utilidades.PI);console.log(Utilidades.formatearFecha(new Date()));console.log(Utilidades.crearId());📝 Resumen: Las clases de TypeScript añaden tipado estático a las clases de JS. Los modificadores public, private y protected controlan el acceso. Las parameter properties reducen boilerplate. implements verifica que una clase cumpla una interfaz. Getters/setters y miembros estáticos completan el ecosistema de clases tipadas.