Principios SOLID en TypeScript: nivel avanzado con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Principios SOLID en TypeScript: teoría y práctica de nivel avanzado



SOLID son cinco principios fundamentales de diseño orientado a objetos que permiten crear código flexible, mantenible y escalable. En TypeScript, gracias al tipado estricto, las interfaces y las clases abstractas, la implementación de estos principios se vuelve especialmente efectiva. En este artículo, analizaremos cada principio a nivel avanzado con ejemplos reales en TypeScript.



1. Single Responsibility Principle (SRP) — Principio de responsabilidad única



Teoría: Cada clase debe tener una única razón para cambiar. En TypeScript, esto significa que un módulo es responsable de exactamente una funcionalidad.



Práctica avanzada: A menudo, la violación del SRP se manifiesta en "objetos divinos" (God Objects). Utilice composición y delegación.



// ❌ Violación de SRP: la clase es responsable de datos, validación y almacenamientoclass UserService {  constructor(private user: User) {}

validateEmail(email: string): boolean { return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email); }

saveToDatabase(): void { // lógica de almacenamiento }

sendWelcomeEmail(): void { // lógica de envío }}

// ✅ SRP: dividimos responsabilidadesinterface IEmailValidator { isValid(email: string): boolean;}

interface IUserRepository { save(user: User): Promise<void>;}

interface INotificationService { sendWelcome(user: User): Promise<void>;}

class UserRegistrationService { constructor( private validator: IEmailValidator, private repository: IUserRepository, private notifier: INotificationService ) {}

async register(user: User): Promise<void> { if (!this.validator.isValid(user.email)) { throw new Error('Invalid email'); } await this.repository.save(user); await this.notifier.sendWelcome(user); }}


2. Open/Closed Principle (OCP) — Principio de abierto/cerrado



Teoría: Las clases deben estar abiertas para la extensión, pero cerradas para la modificación. En TypeScript, esto se logra mediante clases abstractas e interfaces.



Práctica avanzada: Utilice el patrón "Estrategia" (Strategy) para implementar OCP.



// ❌ Violación de OCP: al agregar un nuevo tipo de informe, es necesario modificar la claseclass ReportGenerator {  generate(data: any[], type: string): string {    if (type === 'csv') {      return data.map(row => row.join(',')).join('');    } else if (type === 'json') {      return JSON.stringify(data);    }    // al agregar 'xml' — modificamos este método    throw new Error('Unsupported format');  }}

// ✅ OCP: usamos polimorfismointerface IReportFormatter { format(data: any[]): string;}

class CsvFormatter implements IReportFormatter { format(data: any[]): string { return data.map(row => row.join(',')).join(''); }}

class JsonFormatter implements IReportFormatter { format(data: any[]): string { return JSON.stringify(data); }}

class XmlFormatter implements IReportFormatter { format(data: any[]): string { // implementación para XML return '<data>...</data>'; }}

class ReportGeneratorOCP { constructor(private formatter: IReportFormatter) {}

generate(data: any[]): string { return this.formatter.format(data); }}

// Uso: extendemos sin modificarconst csvReport = new ReportGeneratorOCP(new CsvFormatter());const jsonReport = new ReportGeneratorOCP(new JsonFormatter());


3. Liskov Substitution Principle (LSP) — Principio de sustitución de Barbara Liskov



Teoría: Los objetos en un programa deben ser reemplazables por instancias de sus subtipos sin alterar la corrección del programa. En TypeScript, esto es especialmente crítico debido al tipado nominal.

Blogs

Book Recommendations