Dois lados da mesma moeda: Abordagem Funcional e POO em TypeScript
\n\nO mundo TypeScript é um lugar incrível onde se misturam as melhores práticas de diferentes mundos. Você já se perguntou por que alguns desenvolvedores escrevem código usando classes e herança, enquanto outros usam funções puras e composição? E o principal: qual abordagem trará mais benefícios para o seu projeto?
\n\nNeste artigo, não vamos discutir o que é melhor. Vamos analisar programação funcional versus orientada a objetos em TypeScript com exemplos reais. Você aprenderá quando usar classes e quando usar funções de ordem superior, e como encontrar o meio-termo no desenvolvimento moderno.
\n\nO que é programação funcional em TypeScript?
\n\nProgramação funcional (PF) é um paradigma onde o principal bloco de construção são as funções puras. Elas não alteram o estado externo e sempre retornam o mesmo resultado para as mesmas entradas. O TypeScript suporta muito bem a PF graças à tipagem estrita e às capacidades de trabalhar com funções como dados.
\n\nPrincípios fundamentais da PF em TypeScript
\n- \n
- Imutabilidade — os dados não são alterados, mas sim recriados \n
- Funções puras — sem efeitos colaterais \n
- Composição — construir comportamentos complexos a partir de funções simples \n
- Funções de ordem superior — funções que recebem ou retornam outras funções \n
// Exemplo de funções puras e imutabilidade em TypeScript\ntype User = {\n readonly id: number;\n readonly name: string;\n readonly age: number;\n};\n\nconst addYear = (user: User): User => ({\n ...user,\n age: user.age + 1\n});\n\nconst users: User[] = [\n { id: 1, name: 'Alice', age: 25 },\n { id: 2, name: 'Bob', age: 30 }\n];\n\n// Sem mutações — criamos um novo array\nconst updatedUsers = users.map(addYear);\nconsole.log(users[0].age); // 25 (original não mudou)\nconsole.log(updatedUsers[0].age); // 26\n\n\nObserve o readonly — esta é uma ferramenta poderosa do TypeScript que ajuda a manter a imutabilidade no nível dos tipos.
O que é programação orientada a objetos em TypeScript?
\n\nPOO é construída em torno de objetos que combinam dados e comportamento. O TypeScript adiciona ao JavaScript herança clássica, modificadores de acesso e interfaces, tornando a POO ainda mais expressiva.
\n\nPrincípios fundamentais da POO em TypeScript
\n- \n
- Encapsulamento — ocultação do estado interno através de
privateeprotected\n - Herança — criação de hierarquias de classes \n
- Polimorfismo — interface única para diferentes implementações \n
- Abstração — trabalhar através de interfaces, não de classes concretas \n
// Exemplo de abordagem POO em TypeScript\nabstract class Animal {\n constructor(protected name: string) {}\n\n abstract makeSound(): string;\n\n public introduce(): string {\n return `I am ${this.name}, and I say ${this.makeSound()}`;\n }\n}\n\nclass Dog extends Animal {\n constructor(name: string) {\n super(name);\n }\n\n public makeSound(): string {\n return 'Woof!';\n }\n}\n\nclass Cat extends Animal {\n constructor(name: string) {\n super(name);\n }\n\n public makeSound(): string {\n return 'Meow!';\n }\n}\n\nconst animals: Animal[] = [new Dog('Rex'), new Cat('Whiskers')];\nanimals.forEach(a => console.log(a.introduce()));\n// I am Rex, and I say Woof!\n// I am Whiskers, and I say Meow!\n\n\nAqui, abstract e protected são recursos do TypeScript que não existem no JavaScript comum. Eles permitem construir uma arquitetura rigorosa diretamente no nível dos tipos.
Comparação das abordagens: quando usar cada uma?
\n\nVamos analisar algu