Una clase en TypeScript es una plantilla que define las propiedades y los métodos que tendrán los objetos creados a partir de ella.
TypeScript mejora las clases de JavaScript al agregar tipos explícitos y modificadores de acceso. Esto hace que el código sea más seguro y más fácil de mantener en equipos grandes.
Estructura de una clase en TypeScript
Una clase tiene tres partes principales: propiedades, constructor y métodos.
class NombreClase {
propiedad: tipo;
constructor(parametro: tipo) {
this.propiedad = parametro;
}
metodo(): tipoRetorno {
// lógica
}
}
El constructor es el método especial que se ejecuta cuando creas un nuevo objeto. Los métodos son funciones que pertenecen a la clase.
Tu primera clase: Producto de Liverpool
Imagina que trabajas en Liverpool y necesitas modelar un producto del catálogo.
class Producto {
nombre: string;
precio: number;
disponible: boolean;
constructor(nombre: string, precio: number, disponible: boolean) {
this.nombre = nombre;
this.precio = precio;
this.disponible = disponible;
}
mostrarInfo(): void {
console.log(`${this.nombre} - $${this.precio}`);
console.log(`Disponible: ${this.disponible ? "Sí" : "No"}`);
}
}
const tenis = new Producto("Tenis Nike Air Max", 2800, true);
tenis.mostrarInfo();
Salida en consola:
Tenis Nike Air Max - $2,800
Disponible: Sí
Con new Producto(...) creas una instancia de la clase. Cada instancia tiene sus propios valores.
Modificadores de acceso: public, private y protected
Los modificadores de acceso controlan qué partes del código pueden leer o cambiar una propiedad.
| Modificador | ¿Quién puede acceder? |
|---|---|
public |
Cualquier parte del código (es el valor por defecto) |
private |
Solo dentro de la misma clase |
protected |
Dentro de la clase y en sus clases hijas |
Sin modificador, TypeScript asume que la propiedad es public.
Ejemplo con private: empleado de FEMSA
class Empleado {
nombre: string;
private salario: number;
constructor(nombre: string, salario: number) {
this.nombre = nombre;
this.salario = salario;
}
getSalario(): number {
return this.salario;
}
aplicarAumento(porcentaje: number): void {
this.salario = this.salario * (1 + porcentaje / 100);
}
}
const empleado = new Empleado("Valeria Torres", 18500);
console.log(empleado.nombre); // Valeria Torres
console.log(empleado.getSalario()); // $18,500
empleado.aplicarAumento(10);
console.log(empleado.getSalario()); // $20,350
// Esto causa un ERROR de TypeScript:
// console.log(empleado.salario); ← Property 'salario' is private
El campo salario es private, así que nadie puede leerlo directamente desde fuera. Solo se accede a él a través de getSalario(). Esto se llama encapsulamiento.
Parámetros de constructor abreviados
TypeScript tiene un atajo muy útil. Puedes declarar propiedades directamente en el constructor usando el modificador de acceso.
class Repartidor {
constructor(
public nombre: string,
public zona: string,
private totalEntregas: number
) {}
resumen(): string {
return `${this.nombre} cubre ${this.zona} con ${this.totalEntregas} entregas`;
}
}
const rep = new Repartidor("Luis Méndez", "Guadalajara Norte", 340);
console.log(rep.resumen());
// Luis Méndez cubre Guadalajara Norte con 340 entregas
Esta forma es equivalente a declarar las propiedades arriba y asignarlas en el constructor, pero en mucho menos líneas. Es muy común en proyectos profesionales de TypeScript.
Herencia con extends
La herencia te permite crear una clase nueva basada en una clase existente. La clase hija hereda todas las propiedades y métodos de la clase padre.
class ClaseHija extends ClasePadre {
// propiedades y métodos adicionales
}
Ejemplo: catálogo de Bimbo
class ProductoAlimenticio {
constructor(
public nombre: string,
public precio: number,
public calorias: number
) {}
descripcion(): string {
return `${this.nombre} | $${this.precio} | ${this.calorias} kcal`;
}
}
class PanBimbo extends ProductoAlimenticio {
constructor(
nombre: string,
precio: number,
calorias: number,
public rebanadas: number
) {
super(nombre, precio, calorias);
}
infoPaquete(): string {
return `${this.nombre}: ${this.rebanadas} rebanadas por $${this.precio}`;
}
}
const pan = new PanBimbo("Pan Blanco Grande", 48, 120, 24);
console.log(pan.descripcion());
console.log(pan.infoPaquete());
Salida:
Pan Blanco Grande | $48 | 120 kcal
Pan Blanco Grande: 24 rebanadas por $48
La palabra clave super(...) llama al constructor de la clase padre. Es obligatoria cuando la clase hija tiene un constructor propio.
Sobrescribir métodos con override
Una clase hija puede reemplazar el comportamiento de un método del padre. Esto se llama sobrescritura.
class ProductoMercadoLibre extends Producto {
constructor(
nombre: string,
precio: number,
disponible: boolean,
public vendedor: string
) {
super(nombre, precio, disponible);
}
override mostrarInfo(): void {
super.mostrarInfo();
console.log(`Vendedor: ${this.vendedor}`);
}
}
const articulo = new ProductoMercadoLibre(
"Audífonos Sony",
1200,
true,
"TechStore_MX"
);
articulo.mostrarInfo();
Salida:
Audífonos Sony - $1,200
Disponible: Sí
Vendedor: TechStore_MX
Usar override es una buena práctica. Le dice a TypeScript que estás reemplazando un método del padre intencionalmente, y el compilador te avisa si el método no existe en la clase padre.
La palabra clave readonly
Algunas propiedades no deben cambiar después de que el objeto se crea. Para eso existe readonly.
class Factura {
readonly folio: string;
monto: number;
constructor(folio: string, monto: number) {
this.folio = folio;
this.monto = monto;
}
}
const factura = new Factura("FAC-2024-001", 5600);
console.log(factura.folio); // FAC-2024-001
// Esto causa ERROR:
// factura.folio = "FAC-2024-002"; ← Cannot assign to 'folio' because it is a read-only property
Esto es útil para datos que el SAT o el IMSS requieren que no se modifiquen, como folios fiscales.
Errores comunes
1. Olvidar llamar a super() en la clase hija
Si tu clase hija tiene un constructor y no llamas a super(), TypeScript lanza un error inmediatamente. Siempre llama a super() antes de usar this.
2. Acceder a una propiedad private desde fuera de la clase
const emp = new Empleado("Carlos", 15000);
console.log(emp.salario); // ERROR: Property 'salario' is private
La solución es crear un método get que devuelva el valor, como se mostró en el ejemplo de FEMSA.
3. Confundir la clase con la instancia
La clase es la plantilla. La instancia es el objeto creado con new. No puedes llamar métodos directamente en la clase sin crear una instancia primero.
// INCORRECTO:
Producto.mostrarInfo(); // Error: mostrarInfo is not a static method
// CORRECTO:
const p = new Producto("Camisa", 450, true);
p.mostrarInfo();
4. No usar override al sobrescribir métodos
Sin override, si cambias el nombre del método en el padre, la clase hija no te avisará. Con override, TypeScript detecta el problema automáticamente.
Resumen de modificadores
| Palabra clave | Uso principal |
|---|---|
public |
Acceso libre desde cualquier lugar |
private |
Solo dentro de la misma clase |
protected |
En la clase y sus clases hijas |
readonly |
La propiedad no se puede reasignar después del constructor |
override |
Indica que el método reemplaza al del padre |
Puntos clave
- Las clases en TypeScript combinan propiedades con tipos y métodos en una sola estructura reutilizable.
- Los modificadores
public,privateyprotectedcontrolan desde dónde se puede acceder a cada propiedad. - Puedes declarar propiedades directamente en el constructor usando el modificador de acceso, lo que reduce el código repetitivo.
- La herencia con
extendspermite crear clases especializadas sin repetir código. Recuerda llamar siempre asuper()en el constructor hijo. - Usa
readonlypara propiedades que no deben cambiar después de crearse, como folios o identificadores únicos.