Princípios SOLID em TypeScript: teoria e prática com exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que SOLID é importante no TypeScript



Ao desenvolver em TypeScript, especialmente em projetos grandes, manter a limpeza e flexibilidade do código torna-se criticamente importante. SOLID são cinco princípios fundamentais da programação orientada a objetos que ajudam a criar aplicações escaláveis, facilmente testáveis e sustentáveis. Esses princípios são particularmente relevantes para o TypeScript, que adiciona tipagem estática e interfaces ao JavaScript, fornecendo ferramentas poderosas para sua implementação.



Neste artigo, vamos analisar cada um dos cinco princípios SOLID do ponto de vista do TypeScript, acompanhando a teoria com exemplos práticos de código. Você aprenderá como aplicar esses princípios para melhorar a arquitetura dos seus projetos.



1. Single Responsibility Principle (Princípio da Responsabilidade Única)



Teoria: Cada classe ou módulo deve ter apenas uma razão para mudar. Em outras palavras, a classe deve ser responsável por apenas uma parte da funcionalidade do programa.



Violação do princípio:



// ❌ Ruim: a classe é responsável pelos dados, pela persistência e pela formataçãoclass User {  constructor(public name: string, public email: string) {}

saveToDatabase(): void { console.log(`Salvando ${this.name} no BD`); }

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


Correção aplicando o SRP:



// ✅ Bom: dividimos a responsabilidade em três classesclass User {  constructor(public name: string, public email: string) {}}

class UserRepository { save(user: User): void { console.log(`Salvando ${user.name} no BD`); }}

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


Agora cada classe tem uma única responsabilidade clara, o que simplifica o teste e a alteração do código.



2. Open-Closed Principle (Princípio do Aberto/Fechado)



Teoria: Entidades de software (classes, módulos, funções) devem estar abertas para extensão, mas fechadas para modificação. Isso significa que você deve ser capaz de adicionar novas funcionalidades sem alterar o código existente.



Violação do princípio:



// ❌ Ruim: ao adicionar um novo tipo de forma, é necessário alterar a classe 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;  }}


Correção aplicando o OCP:



// ✅ Bom: usamos interface e 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(); // Fechado para modificação, aberto para extensão }}


Agora, para adicionar uma nova forma (por exemplo, Triangle), basta criar uma nova classe que implemente a interface Shape — sem alterar o AreaCalculator.



3. Liskov Substitution Principle (Princípio da Substituição de Liskov)



Teoria: Os objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem quebrar a correção do programa. Se você tem uma classe base e uma classe derivada, o código que funciona com a classe base deve funcionar corretamente também com a classe derivada.



Violação do princípio:



// ❌ Ruim                

Blogs

Book Recommendations