Deux faces d'une même médaille : approches Fonctionnelle et POO en TypeScript
\n\nLe monde de TypeScript est un endroit fascinant où se mélangent les meilleures pratiques de différents univers. Vous êtes-vous déjà demandé pourquoi certains développeurs écrivent du code en utilisant des classes et l'héritage, tandis que d'autres utilisent des fonctions pures et la composition ? Et surtout : quelle approche apportera le plus de bénéfices à votre projet ?
\n\nDans cet article, nous ne débattrons pas de ce qui est le meilleur. Nous analyserons la programmation fonctionnelle contre la programmation orientée objet en TypeScript avec des exemples concrets. Vous apprendrez quand utiliser les classes et quand utiliser les fonctions d'ordre supérieur, et comment trouver le juste milieu dans le développement moderne.
\n\nQu'est-ce que la programmation fonctionnelle en TypeScript ?
\n\nLa programmation fonctionnelle (PF) est un paradigme où les fonctions pures sont les blocs de construction principaux. Elles ne modifient pas l'état externe et retournent toujours le même résultat pour les mêmes données d'entrée. TypeScript supporte très bien la PF grâce à son typage strict et à ses capacités de traitement des fonctions en tant que données.
\n\nPrincipes fondamentaux de la PF en TypeScript
\n- \n
- Immutabilité — les données ne sont pas modifiées, mais recréées \n
- Fonctions pures — aucun effet de bord \n
- Composition — assembler un comportement complexe à partir de fonctions simples \n
- Fonctions d'ordre supérieur — fonctions qui prennent ou retournent d'autres fonctions \n
// Exemple de fonctions pures et d'immutabilité en TypeScript\ntype User = {\n readonly id: number;\n readonly name: string;\n readonly age: number;\n};\n\nconst addYear = (user: User): User => ({\n ...user,\n age: user.age + 1\n});\n\nconst users: User[] = [\n { id: 1, name: 'Alice', age: 25 },\n { id: 2, name: 'Bob', age: 30 }\n];\n\n// Aucune mutation — on crée un nouveau tableau\nconst updatedUsers = users.map(addYear);\nconsole.log(users[0].age); // 25 (l'original n'a pas changé)\nconsole.log(updatedUsers[0].age); // 26\n\n\nRemarquez readonly — c'est un outil puissant de TypeScript qui aide à respecter l'immutabilité au niveau des types.
Qu'est-ce que la programmation orientée objet en TypeScript ?
\n\nLa POO est construite autour d'objets qui combinent données et comportement. TypeScript ajoute à JavaScript l'héritage classique, les modificateurs d'accès et les interfaces, rendant la POO encore plus expressive.
\n\nPrincipes fondamentaux de la POO en TypeScript
\n- \n
- Encapsulation — masquage de l'état interne via
privateetprotected\n - Héritage — création de hiérarchies de classes \n
- Polymorphisme — interface unique pour différentes implémentations \n
- Abstraction — travail via des interfaces, plutôt que des classes concrètes \n
// Exemple d'approche POO en TypeScript\nabstract class Animal {\n constructor(protected name: string) {}\n\n abstract makeSound(): string;\n\n public introduce(): string {\n return `Je suis ${this.name}, et je dis ${this.makeSound()}`;\n }\n}\n\nclass Dog extends Animal {\n constructor(name: string) {\n super(name);\n }\n\n public makeSound(): string {\n return 'Ouaf !';\n }\n}\n\nclass Cat extends Animal {\n constructor(name: string) {\n super(name);\n }\n\n public makeSound(): string {\n return 'Miaou !';\n }\n}\n\nconst animals: Animal[] = [new Dog('Rex'), new Cat('Minou')];\nanimals.forEach(a => console.log(a.introduce()));\n// Je suis Rex, et je dis Ouaf !\n// Je suis Minou, et je dis Miaou !\n\n\nIci, abstract et protected sont des fonctionnalités de TypeScript qui n'existent pas en JavaScript standard. Elles permettent de construire une architecture stricte directement au niveau des types.
Comparaison des approches : quand utiliser quoi ?
\n\nAnalysons quelqu