Principios SOLID en TypeScript: teoría y práctica 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

Introducción: Por qué SOLID es importante en TypeScript



Al desarrollar con TypeScript, especialmente en proyectos grandes, mantener la limpieza y flexibilidad del código se vuelve críticamente importante. SOLID son cinco principios fundamentales de la programación orientada a objetos que ayudan a crear aplicaciones escalables, fácilmente testeables y mantenibles. Estos principios son particularmente relevantes para TypeScript, que añade tipado estático e interfaces a JavaScript, proporcionando herramientas poderosas para su implementación.



En este artículo, analizaremos cada uno de los cinco principios SOLID desde la perspectiva de TypeScript, acompañando la teoría con ejemplos prácticos de código. Aprenderás cómo aplicar estos principios para mejorar la arquitectura de tus proyectos.



1. Single Responsibility Principle (Principio de Responsabilidad Única)



Teoría: Cada clase o módulo debe tener una sola razón para cambiar. En otras palabras, una clase debe ser responsable de una sola parte de la funcionalidad del programa.



Violación del principio:



// ❌ Malo: la clase es responsable de los datos, el guardado y el formateoclass User {  constructor(public name: string, public email: string) {}

saveToDatabase(): void { console.log(`Guardando ${this.name} en la BD`); }

generateHTML(): string { return `<div>${this.name} - ${this.email}</div>`; }}


Corrección aplicando SRP:



// ✅ Bueno: dividimos la responsabilidad en tres clasesclass User {  constructor(public name: string, public email: string) {}}

class UserRepository { save(user: User): void { console.log(`Guardando ${user.name} en la BD`); }}

class UserView { render(user: User): string { return `<div>${user.name} - ${user.email}</div>`; }}


Ahora cada clase tiene una única responsabilidad clara, lo que simplifica el testeo y la modificación del código.



2. Open-Closed Principle (Principio de Abierto/Cerrado)



Teoría: Las entidades de software (clases, módulos, funciones) deben estar abiertas para la extensión, pero cerradas para la modificación. Esto significa que debes poder añadir nueva funcionalidad sin cambiar el código existente.



Violación del principio:



// ❌ Malo: al añadir un nuevo tipo de figura, hay que modificar la clase AreaCalculatorclass AreaCalculator {  calculate(shape: any): number {    if (shape.type === 'circle') {      return Math.PI * shape.radius ** 2;    } else if (shape.type === 'rectangle') {      return shape.width * shape.height;    }    return 0;  }}


Corrección aplicando OCP:



// ✅ Bueno: usamos una interfaz y polimorfismointerface Shape {  area(): number;}

class Circle implements Shape { constructor(public radius: number) {} area(): number { return Math.PI * this.radius ** 2; }}

class Rectangle implements Shape { constructor(public width: number, public height: number) {} area(): number { return this.width * this.height; }}

class AreaCalculator { calculate(shape: Shape): number { return shape.area(); // Cerrado para modificación, abierto para extensión }}


Ahora para añadir una nueva figura (por ejemplo, Triangle) basta con crear una nueva clase que implemente la interfaz Shape — sin modificar AreaCalculator.



3. Liskov Substitution Principle (Principio de Sustitución de Liskov)



Teoría: Los objetos en un programa deben ser reemplazables por instancias de sus subtipos sin alterar la corrección del programa. Si tienes una clase base y una clase derivada, el código que funciona con la clase base debe funcionar correctamente también con la clase derivada.



Violación del principio:



// ❌ Malo                

Blogs

Book Recommendations