Programmation fonctionnelle en TypeScript : de A à Z
La programmation fonctionnelle (PF) est un paradigme qui considère le calcul comme l'évaluation de fonctions mathématiques et évite les changements d'état et les données mutables. TypeScript, en tant qu'extension fortement typée de JavaScript, offre une excellente base pour appliquer les principes de la PF, permettant d'écrire un code plus prévisible, testable et fiable. Dans cet article, nous allons détailler les concepts clés de la PF en TypeScript, en commençant par les bases et en allant jusqu'aux techniques avancées.
Principes fondamentaux de la programmation fonctionnelle
Avant de plonger dans le code, il est important de comprendre les principes fondamentaux sur lesquels repose la PF.
Fonctions pures (Pure Functions)
Une fonction pure est une fonction qui :
- Retourne toujours le même résultat pour les mêmes arguments (déterminisme).
- N'a pas d'effets secondaires (ne modifie pas les variables externes, n'affiche pas de données dans la console, n'envoie pas de requêtes).
Exemple de fonction pure :
function add(a: number, b: number): number { return a + b;}
// Toujours prévisibleconsole.log(add(2, 3)); // 5console.log(add(2, 3)); // 5Exemple de fonction impure :
let counter = 0;function increment(): number { return ++counter; // Effet secondaire : modification d'une variable externe}Immutabilité (Immutability)
Les données ne doivent pas être modifiées après leur création. Au lieu de modifier un objet existant, on crée une nouvelle copie avec les modifications nécessaires.
interface User { name: string; age: number;}
const user: User = { name: "Alice", age: 30 };
// Mauvais (mutation)user.age = 31;
// Bon (immuabilité)const updatedUser: User = { ...user, age: 31 };
console.log(user); // { name: "Alice", age: 30 } - l'original n'a pas changéconsole.log(updatedUser); // { name: "Alice", age: 31 }Composition et curryfication en TypeScript
La composition de fonctions est le processus qui consiste à combiner plusieurs fonctions simples pour en créer une plus complexe. La curryfication (currying) est la transformation d'une fonction à plusieurs arguments en une séquence de fonctions, chacune prenant un seul argument.
Composition (Function Composition)
Implémentation typée de la composition en TypeScript :
function compose<A, B, C>(f: (x: B) => C, g: (x: A) => B): (x: A) => C { return (x: A) => f(g(x));}
const toUpperCase = (str: string): string => str.toUpperCase();const exclaim = (str: string): string => `${str}!`;
const shout = compose(exclaim, toUpperCase);console.log(shout("hello world")); // "HELLO WORLD!"Curryfication (Currying)
Exemple de fonction curryfiée :
function multiply(a: number): (b: number) => number { return (b: number) => a * b;}
const double = multiply(2);const triple = multiply(3);
console.log(double(5)); // 10console.log(triple(5)); // 15La curryfication rend les fonctions plus flexibles et pratiques pour la composition.
Travail avec les monades : Option et Result
Les monades sont un puissant patron pour gérer les effets secondaires et la gestion des erreurs sans violer la pureté des fonctions. En TypeScript, on utilise souvent les monades Option (ou Maybe) et Result (ou Either).
Monade Option (Maybe)
Permet de travailler en toute sécurité avec des valeurs qui peuvent être null ou undefined.
type Option<T> = T | null;
function safeDivide(a: number, b: number): Option<number> { return b === 0 ? null : a / b;}
function getValue(value: Option<number>): string { if (value === null) { return "Erreur : division par zéro"; } return `Résultat : ${value}`;}
console.log(getValue(safeDivide(10, 2)