Programação Funcional em TypeScript: Fundamentos e Prática

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

Programação Funcional em TypeScript: da teoria à prática



Programação Funcional (PF) é um paradigma no qual os cálculos são tratados como avaliação de funções matemáticas e evita-se a mudança de estado e dados mutáveis. TypeScript, sendo uma extensão do JavaScript, é excelente para aplicar princípios de PF devido à sua tipagem forte e suporte a funções de alta ordem. Neste artigo, vamos analisar os conceitos-chave de PF em TypeScript e mostrar como aplicá-los na prática.



1. Funções Puras e Imutabilidade



Função Pura é uma função que:

  • Sempre retorna o mesmo resultado para os mesmos argumentos (determinismo).
  • Não tem efeitos colaterais (não altera variáveis externas, não exibe dados, não faz requisições).


Exemplo de função pura:

// Função pura: soma dois númerosconst add = (a: number, b: number): number => a + b;

// Sempre retornará 5console.log(add(2, 3)); // 5console.log(add(2, 3)); // 5


Imutabilidade é o princípio onde os dados não são alterados após a criação. Em vez de modificar um objeto existente, cria-se um novo.



// Atualização imutável de arrayconst numbers: number[] = [1, 2, 3];

// Ruim (mutação):numbers.push(4);

// Bom (imutável):const newNumbers = [...numbers, 4]; // [1,2,3,4]

// Atualização imutável de objetointerface User { name: string; age: number;}

const user: User = { name: 'Alice', age: 30 };const updatedUser: User = { ...user, age: 31 }; // novo objeto


2. Composição de Funções e Currying



Composição de funções é a combinação de duas ou mais funções em uma nova. O resultado da primeira função é passado como argumento para a segunda.



// Composição de duas funçõesconst compose = <T, U, V>(f: (x: U) => V, g: (x: T) => U) =>  (x: T): V => f(g(x));

const double = (x: number): number => x * 2;const increment = (x: number): number => x + 1;

const doubleThenIncrement = compose(increment, double);console.log(doubleThenIncrement(3)); // (3*2)+1 = 7


Currying é a transformação de uma função com múltiplos argumentos em uma sequência de funções com um único argumento.



// Função normalconst multiply = (a: number, b: number): number => a * b;

// Versão curriedconst curriedMultiply = (a: number) => (b: number): number => a * b;

const multiplyBy2 = curriedMultiply(2);console.log(multiplyBy2(5)); // 10console.log(multiplyBy2(7)); // 14


Currying simplifica a aplicação parcial e o reuso de funções.



3. Functors e Mônadas: Maybe e Either



Functor é um contêiner que implementa o método map, permitindo aplicar uma função ao valor dentro do contêiner. Em TypeScript, um array é um exemplo de functor:



const numbers = [1, 2, 3];const doubled = numbers.map(x => x * 2); // [2, 4, 6]


Mônada é um functor que adicionalmente implementa os métodos flatMap (ou bind) e of (ou return). Mônadas ajudam a lidar com efeitos colaterais, valores null e erros sem exceções.



Vamos implementar uma mônada simples Maybe para trabalhar com null/undefined de forma segura:



// Mônada Maybeclass Maybe<T> {  private constructor(private value: T | null) {}

static of<T>(value: T): Maybe<T> { return new Maybe(value); }

static none<T>(): Maybe<T> { return new Maybe<T>(null); }

map<U>(fn: (value: T) => U): Maybe<U> { if (this.value === null || this.value === undefined) { return Maybe.none(); } return M

Blogs

Book Recommendations