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 em TypeScript



SOLID é um acrônimo de cinco princípios fundamentais de design orientado a objetos, formulados por Robert Martin (Uncle Bob). No contexto do TypeScript, esses princípios adquirem valor especial devido ao sistema de tipos estrito e ao suporte a paradigmas modernos de OOP. A aplicação do SOLID torna o código mais flexível, testável e sustentável, o que é criticamente importante para projetos escaláveis.



Neste artigo, vamos analisar cada princípio SOLID com exemplos práticos em TypeScript, mostrar antipadrões e suas implementações corretas. Você aprenderá como escrever código que não quebra ao adicionar novas funcionalidades.



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



Teoria

Cada classe deve ter apenas um motivo para ser alterada. Isso significa que a classe deve ser responsável por apenas uma parte da funcionalidade do programa. Se uma classe executa várias tarefas, é mais difícil de manter e testar.



Antipadrão (violação do SRP)

class UserService {    saveUser(user: User): void {        // Salvar no BD        console.log('User saved');    }

sendEmail(user: User, message: string): void { // Enviar email console.log(`Email sent to ${user.email}`); }

generateReport(user: User): string { // Gerar relatório return `Report for ${user.name}`; }}


Implementação correta (SRP)

class UserRepository {    save(user: User): void {        // Apenas salvar    }}

class EmailService { send(user: User, message: string): void { // Apenas enviar email }}

class ReportGenerator { generate(user: User): string { // Apenas gerar relatórios }}


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



Teoria

As classes devem estar abertas para extensão, mas fechadas para modificação. Novas funcionalidades devem ser adicionadas através de herança ou composição, e não alterando o código existente.



Antipadrão (violação do OCP)

class PaymentProcessor {    processPayment(type: string, amount: number): void {        if (type === 'card') {            // Processar cartão        } else if (type === 'paypal') {            // Processar PayPal        } else if (type === 'crypto') {            // Processar criptomoeda        }        // Ao adicionar um novo tipo — é necessário alterar a classe!    }}


Implementação correta (OCP)

interface PaymentMethod {    process(amount: number): void;}

class CardPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing card payment: $${amount}`); }}

class PayPalPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing PayPal payment: $${amount}`); }}

class PaymentProcessor { constructor(private paymentMethod: PaymentMethod) {}

process(amount: number): void { this.paymentMethod.process(amount); }}


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



Teoria

Objetos da classe base devem ser substituíveis por objetos de suas subclasses sem quebrar o funcionamento do programa. As subclasses não devem alterar o comportamento esperado da classe base.



Antipadrão (violação do LSP)

class Rectangle {    constructor(public width: number, public height: number) {}

setWidth(width: number): void { this.width = width; }

setHeight(height: number): void { this.height = height; }

getArea(): number { return this.width * this.height; }}

class Square extends Rectangle {

Blogs

Book Recommendations