Como usar TypeScript para programação funcional

O TypeScript oferece recursos poderosos que complementam a programação funcional, como tipagem forte e inferência de tipo avançada. Este artigo explora como aproveitar o TypeScript para implementar princípios de programação funcional de forma eficaz.

Princípios-chave da programação funcional

A programação funcional enfatiza a imutabilidade, funções puras e funções de ordem superior. Esses princípios podem ser efetivamente implementados em TypeScript para construir código robusto e sustentável.

Imutabilidade

Imutabilidade se refere ao conceito de dados não serem modificados após a criação. TypeScript pode impor imutabilidade por meio de definições de tipo e tipos utilitários.

type ReadonlyUser = {
  readonly id: number;
  readonly name: string;
};

const user: ReadonlyUser = {
  id: 1,
  name: 'Alice',
};

// The following line will result in a TypeScript error
// user.id = 2;

Funções Puras

Funções puras são funções que sempre produzem a mesma saída dada a mesma entrada e não têm efeitos colaterais. O sistema de tipos do TypeScript ajuda a garantir que as funções aderem à pureza.

const add = (a: number, b: number): number => {
  return a + b;
};

const result = add(2, 3); // 5

Funções de ordem superior

Funções de ordem superior são funções que recebem outras funções como argumentos ou as retornam como resultados. O TypeScript pode digitar essas funções para garantir que sejam usadas corretamente.

const applyFunction = <T>(fn: (x: T) => T, value: T): T => {
  return fn(value);
};

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

const result = applyFunction(increment, 5); // 6

Composição de funções

A composição de funções envolve combinar múltiplas funções para criar uma nova função. O sistema de tipos do TypeScript pode ser usado para garantir que funções compostas tenham tipos corretos.

const compose = <T, U, V>(f: (arg: U) => V, g: (arg: T) => U) => (x: T): V => {
  return f(g(x));
};

const double = (x: number): number => x * 2;
const square = (x: number): number => x * x;

const doubleThenSquare = compose(square, double);

const result = doubleThenSquare(3); // 36

Inferência de Tipos e Genéricos

A inferência de tipos e os genéricos do TypeScript permitem a criação de componentes funcionais reutilizáveis, mantendo ao mesmo tempo uma forte segurança de tipos.

const map = <T, U>(arr: T[], fn: (item: T) => U): U[] => {
  return arr.map(fn);
};

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

Conclusão

O TypeScript aprimora a programação funcional ao fornecer segurança de tipo e tipos expressivos. Ao aplicar princípios como imutabilidade, funções puras e funções de ordem superior, o TypeScript pode ser usado para construir aplicativos escaláveis ​​e sustentáveis.