Cómo utilizar TypeScript para programación funcional

TypeScript ofrece potentes funciones que complementan la programación funcional, como la tipificación estricta y la inferencia de tipos avanzada. Este artículo explora cómo aprovechar TypeScript para implementar principios de programación funcional de manera eficaz.

Principios clave de la programación funcional

La programación funcional enfatiza la inmutabilidad, las funciones puras y las funciones de orden superior. Estos principios se pueden implementar de manera eficaz en TypeScript para crear código sólido y fácil de mantener.

Inmutabilidad

La inmutabilidad se refiere al concepto de que los datos no se modifican después de su creación. TypeScript puede aplicar la inmutabilidad a través de definiciones de tipos y tipos de utilidad.

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;

Funciones puras

Las funciones puras son funciones que siempre producen el mismo resultado con la misma entrada y no tienen efectos secundarios. El sistema de tipos de TypeScript ayuda a garantizar que las funciones respeten la pureza.

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

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

Funciones de orden superior

Las funciones de orden superior son funciones que toman otras funciones como argumentos o las devuelven como resultados. TypeScript puede tipificar estas funciones para garantizar que se utilicen correctamente.

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

Composición de funciones

La composición de funciones implica combinar varias funciones para crear una nueva función. El sistema de tipos de TypeScript se puede utilizar para garantizar que las funciones compuestas tengan los tipos correctos.

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

Inferencia de tipos y genéricos

La inferencia de tipos y los genéricos de TypeScript permiten crear componentes funcionales reutilizables manteniendo al mismo tiempo una fuerte seguridad 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]

Conclusión

TypeScript mejora la programación funcional al brindar seguridad de tipos y tipos expresivos. Al aplicar principios como la inmutabilidad, las funciones puras y las funciones de orden superior, TypeScript se puede utilizar para crear aplicaciones escalables y fáciles de mantener.