Lección 8 de 20 · Lectura y práctica
Quiz: Patrones de Diseño en TypeScript
Tipo de lección: QuizConcepto claveLos patrones de diseño en TypeScript son soluciones reutilizables a problemas comunes en el desarrollo de software, pero con un enfoque especial en el sistema de tipos. A nivel avanzado, no se.
Del concepto a la práctica
Taller de esta lección
La elección del patrón depende del problema: Factory centraliza creación, Builder ordena pasos y una unión discriminada limita variantes. Este caso permite compararlos sin añadir clases innecesarias.
Ejemplo resuelto
type Parser = { format: "csv"; parse(s: string): string[] } | { format: "line"; parse(s: string): string[] };
const parser: Parser = { format: "csv", parse: s => s.split(",") };
console.log(parser.parse("a,b")); // ["a", "b"]Pruébalo
Decide si una nueva instancia necesita Factory o solo un literal.
Implementa el formato
lineconsplit("|").Procesa
"x|y".Rechaza una variante sin
parse.
Comprueba tu resultado
El separador de barras debe devolver ["x","y"]; el de comas devuelve ["a","b"].
Error frecuente: crear una jerarquía de clases para dos comportamientos simples. Corrígelo manteniendo una unión y funciones pequeñas; usa una Factory solo si la selección o construcción se repite en varios consumidores.
Este split por comas es un ejemplo de separación simple, no un parser CSV completo: no admite comas entre comillas, escapes ni saltos dentro de un campo. El formato llamado line en el ejercicio usa barras; documenta ese contrato aunque su nombre sea simplificado. Una unión con ambas firmas iguales conserva la etiqueta, pero no demuestra un Builder ni una jerarquía. Justifica la Factory cuando centralizas selección repetida, sin añadirla por obligación.

Mapa de prácticaUna condición decide qué camino ejecuta el programa. Un bucle repite una operación mientras queden elementos, y termina cuando la lista se agota. Separar ambas ideas ayuda a seguir el flujo y comprobar casos límite.
Ver la infografía en tamaño completo ↗Fuentes para profundizar
Tipo de lección: Quiz
Concepto clave
Los patrones de diseño en TypeScript son soluciones reutilizables a problemas comunes en el desarrollo de software, pero con un enfoque especial en el sistema de tipos. A nivel avanzado, no se trata solo de implementar patrones clásicos como Singleton o Factory, sino de aprovechar el tipado genérico para hacerlos más seguros, flexibles y adaptables a arquitecturas complejas.
Imagina que estás construyendo una biblioteca de componentes frontend. Sin patrones de diseño, cada componente podría tener su propia lógica ad-hoc, lo que lleva a código duplicado y difícil de mantener. Con patrones bien aplicados y tipados, puedes crear una arquitectura coherente donde los tipos guían el uso correcto y previenen errores en tiempo de compilación. Por ejemplo, el patrón Strategy con genéricos permite definir algoritmos intercambiables con tipos específicos para cada contexto, asegurando que solo se usen las estrategias válidas.
Cómo funciona en la práctica
Vamos a implementar el patrón Observer con TypeScript avanzado, usando genéricos para tipar los eventos y sus datos. Este patrón es clave en arquitecturas reactivas, como en sistemas de estado o notificaciones.
// Definición de tipos genéricos para Observer
interface EventData {
type: string;
payload: any;
}
class Observable {
private observers: Array<(event: T) => void> = [];
subscribe(observer: (event: T) => void): void {
this.observers.push(observer);
}
notify(event: T): void {
this.observers.forEach(observer => observer(event));
}
}
// Uso con tipos concretos
type UserEvent = { type: 'login'; payload: { userId: string } } | { type: 'logout'; payload: null };
const userObservable = new Observable();
userObservable.subscribe(event => {
if (event.type === 'login') {
console.log(`Usuario ${event.payload.userId} ha iniciado sesión`);
}
});
// TypeScript previene errores: userObservable.notify({ type: 'error', payload: 'msg' }); // Error de tipo En este ejemplo, el genérico T restringe los eventos a tipos específicos, evitando notificaciones con datos incorrectos. Esto es crucial en libs donde los usuarios deben seguir contratos de tipos bien definidos.
Caso de estudio
Supongamos que eres Frontend Engineer en una empresa que desarrolla una app de e-commerce con una arquitectura compleja basada en micro-frontends. Necesitas un sistema de gestión de estado que sea tipo-seguro y escalable. Implementa el patrón State con TypeScript para manejar el estado del carrito de compras.
// Estados posibles del carrito
type CartState = 'empty' | 'adding' | 'full' | 'checkout';
class CartContext {
private state: T;
constructor(initialState: T) {
this.state = initialState;
}
transition(newState: U): CartContext {
// Lógica de transición con validación de tipos
if (this.state === 'empty' && newState === 'adding') {
return new CartContext(newState);
}
// Otras transiciones...
throw new Error('Transición inválida');
}
getState(): T {
return this.state;
}
}
// Uso en la app
const cart = new CartContext('empty');
const updatedCart = cart.transition('adding'); // Válido
// const invalidCart = cart.transition('checkout'); // Error en tiempo de compilación si no es válido Este enfoque asegura que las transiciones de estado sean tipadas y predecibles, reduciendo bugs en flujos complejos. En una lib, podrías exportar estos tipos para que otros desarrolladores los usen correctamente.
Errores comunes
- Usar any en genéricos: Evita
class Example, ya que pierdes los beneficios del tipado. En su lugar, define restricciones claras, comoT extends EventData. - No tipar retornos de métodos en patrones: En el patrón Factory, asegúrate de que los métodos devuelvan tipos concretos, no
any, para que TypeScript pueda inferir y validar usos. - Ignorar la inferencia de tipos: No sobre-tipes cuando TypeScript puede inferir; por ejemplo, en
new Observable, el genérico se infiere automáticamente.() - Implementar patrones sin considerar arquitectura: No apliques patrones por moda; evalúa si resuelven un problema real en tu contexto, como la escalabilidad en micro-frontends.
- Olvidar documentar contratos de tipos: En libs, documenta los tipos esperados para patrones, usando comentarios JSDoc o archivos .d.ts, para facilitar el uso por otros equipos.
Checklist de dominio
- ¿Puedes implementar al menos 3 patrones de diseño (ej., Observer, Factory, Strategy) con genéricos en TypeScript?
- ¿Sabes usar conditional types o mapped types para hacer patrones más flexibles, como en Builder o Proxy?
- ¿Eres capaz de detectar y corregir errores de tipo en implementaciones de patrones existentes?
- ¿Puedes diseñar una pequeña lib que exporte patrones tipados para reuso en proyectos?
- ¿Entiendes cómo los patrones con TypeScript mejoran la mantenibilidad en arquitecturas complejas, como micro-frontends?
- ¿Has aplicado patrones en proyectos reales, midiendo su impacto en reducción de bugs o mejora de performance?
- ¿Puedes explicar a un compañero la diferencia entre un patrón clásico y su versión con tipado avanzado en TypeScript?
Implementa un Patrón Factory Tipado para una Librería de Componentes UI
En este ejercicio, crearás un patrón Factory con TypeScript avanzado para generar componentes de UI en una librería frontend. Sigue estos pasos:
- Define una interfaz genérica
UIComponentcon un métodorender()que devuelva un string (simulando HTML). - Crea clases concretas como
ButtonyInputque implementenUIComponent, con propiedades específicas tipadas (ej.,label: stringpara Button). - Implementa una clase
ComponentFactorycon un método genéricocreateComponent<T extends UIComponent>(type: string, props: ...): Tque instancie el componente correcto basado en el tipo. - Asegúrate de que TypeScript infiera los tipos de las propiedades y prevenga errores, como pasar un
labela un Input. - Prueba la factory creando un Button y un Input, y llama a sus métodos
render()para ver el output.
Objetivo: Practicar el uso de genéricos y tipos para hacer un patrón Factory seguro y reutilizable en arquitecturas de libs.
Pistas
- Usa un tipo union para los tipos de componente permitidos, como 'button' | 'input'.
- Considera usar conditional types en las props para mapear el tipo de componente a sus propiedades específicas.
- En la factory, usa una estructura de datos como un mapa para asociar tipos con clases constructoras.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con TypeScript Avanzado: Patrones Genéricos y Tipado Profundo para Arquitecturas Complejas
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.