Comment utiliser TypeScript pour la programmation fonctionnelle

TypeScript propose des fonctionnalités puissantes qui complètent la programmation fonctionnelle, telles que le typage fort et l'inférence de type avancée. Cet article explique comment exploiter TypeScript pour mettre en œuvre efficacement les principes de programmation fonctionnelle.

Principes clés de la programmation fonctionnelle

La programmation fonctionnelle met l'accent sur l'immuabilité, les fonctions pures et les fonctions d'ordre supérieur. Ces principes peuvent être efficacement mis en œuvre dans TypeScript pour créer un code robuste et maintenable.

Immutabilité

L'immuabilité fait référence au concept selon lequel les données ne sont pas modifiées après leur création. TypeScript peut imposer l'immuabilité grâce à des définitions de type et des types utilitaires.

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;

Fonctions pures

Les fonctions pures sont des fonctions qui produisent toujours le même résultat à partir de la même entrée et qui n'ont pas d'effets secondaires. Le système de types de TypeScript permet de garantir que les fonctions respectent la pureté.

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

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

Fonctions d'ordre supérieur

Les fonctions d'ordre supérieur sont des fonctions qui prennent d'autres fonctions comme arguments ou les renvoient comme résultats. TypeScript peut typer ces fonctions pour garantir qu'elles sont utilisées correctement.

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

Composition de la fonction

La composition de fonctions consiste à combiner plusieurs fonctions pour créer une nouvelle fonction. Le système de types de TypeScript peut être utilisé pour garantir que les fonctions composées ont les types corrects.

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

Inférence de type et génériques

L'inférence de type et les génériques de TypeScript permettent de créer des composants fonctionnels réutilisables tout en maintenant une sécurité de type élevée.

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]

Conclusion

TypeScript améliore la programmation fonctionnelle en offrant une sécurité de type et des types expressifs. En appliquant des principes tels que l'immuabilité, les fonctions pures et les fonctions d'ordre supérieur, TypeScript peut être utilisé pour créer des applications évolutives et maintenables.