Princípios SOLID em TypeScript: nível avançado 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

Princípios SOLID em TypeScript: teoria e prática de nível avançado



SOLID — são cinco princípios fundamentais de design orientado a objetos que permitem criar código flexível, sustentável e escalável. Em TypeScript, graças à tipagem forte, interfaces e classes abstratas, a implementação desses princípios torna-se especialmente eficaz. Neste artigo, analisaremos cada princípio em nível avançado com exemplos reais em TypeScript.



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



Teoria: Cada classe deve ter apenas um motivo para mudar. Em TypeScript, isso significa que o módulo é responsável por exatamente uma funcionalidade.



Prática avançada: Frequentemente, a violação do SRP se manifesta em "objetos divinos" (God Objects). Use composição e delegação.



// ❌ Violação do SRP: a classe é responsável por dados, validação e persistênciaclass UserService {  constructor(private user: User) {}

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

saveToDatabase(): void { // lógica de persistência }

sendWelcomeEmail(): void { // lógica de envio }}

// ✅ SRP: separando 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('Email inválido'); } await this.repository.save(user); await this.notifier.sendWelcome(user); }}


2. Open/Closed Principle (OCP) — Princípio Aberto/Fechado



Teoria: As classes devem estar abertas para extensão, mas fechadas para modificação. Em TypeScript, isso é alcançado por meio de classes abstratas e interfaces.



Prática avançada: Use o padrão "Strategy" (Estratégia) para implementar o OCP.



// ❌ Violação do OCP: ao adicionar um novo tipo de relatório, é necessário modificar a classeclass 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);    }    // ao adicionar 'xml' — modificamos este método    throw new Error('Formato não suportado');  }}

// ✅ OCP: usando 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 { // implementação para XML return '<data>...</data>'; }}

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

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

// Uso: estendemos sem modificaçãoconst csvReport = new ReportGeneratorOCP(new CsvFormatter());const jsonReport = new ReportGeneratorOCP(new JsonFormatter());


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



Teoria: Os objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem alterar a correção do programa. Em TypeScript, isso é especialmente crítico devido à tipagem nominativa.

Blogs

Book Recommendations