Pourquoi le typage est un super-pouvoir, pas un fardeau
\n\nImaginez : vous écrivez du code, tout fonctionne, vous êtes heureux. Et puis — boum ! — une erreur rouge dans la console : Cannot read property 'name' of undefined. Ça vous parle ? Bienvenue dans le monde du JavaScript sans types. Mais bonne nouvelle : le JavaScript moderne (et surtout TypeScript) offre un outil puissant — les Generics (génériques). Ce n'est pas juste « une fonctionnalité de plus », mais un vrai moyen de rendre le code plus propre, plus sûr et plus compréhensible.
Dans cet article, nous allons voir ce qu'est le typage en JavaScript, comment fonctionnent les generics et pourquoi les utiliser dans chaque projet. Pas de théorie aride — seulement des exemples concrets et des conseils pratiques.
\n\nQue sont les Generics et pourquoi en a-t-on besoin ?
\n\nLes Generics (types génériques) sont un mécanisme qui permet d'écrire des fonctions, des classes et des interfaces qui fonctionnent avec différents types de données, tout en conservant un typage strict. En termes simples : vous créez un code « universel » qui s'adapte automatiquement au type de données avec lequel il travaille.
\n\nSans génériques, vous écririez quelque chose comme :
\n\nfunction identity(arg: any): any {\n return arg;\n}\n\nLe problème ? any tue tout le typage. Vous perdez l'information sur le type, et le compilateur ne peut pas vous avertir d'une erreur. Avec les Generics, c'est différent :
function identity<T>(arg: T): T {\n return arg;\n}\n\n// Utilisation\nlet num = identity<number>(42); // type number\nlet str = identity<string>("Bonjour"); // type string\n\nDe la magie ? Non, juste un typage intelligent. Le type T est un placeholder qui est remplacé par le type réel lors de l'appel de la fonction.
Generics vs any : la bataille pour la sécurité
\n\nBeaucoup de débutants demandent : « Pourquoi se compliquer avec les génériques si on peut simplement utiliser any ? » La réponse est simple : la sécurité des types n'est pas une question d'esthétique, mais de prévention des bugs à l'exécution.
Regardez cet exemple sans Generics :
\n\nfunction getLength(data: any): number {\n return data.length; // si data est un nombre, il y aura une erreur\n}\n\ngetLength(42); // undefined à l'exécution\n\n\nAvec les génériques, vous indiquez explicitement que la fonction travaille avec des tableaux ou des chaînes :
\n\nfunction getLength<T extends { length: number }>(data: T): number {\n return data.length;\n}\n\ngetLength([1,2,3]); // 3\ngetLength("hello"); // 5\n// getLength(42); // Erreur de compilation — un nombre n'a pas de length\n\n\nVous voyez la différence ? L'erreur est détectée au moment de l'écriture du code, pas en production. C'est l'essence même du typage avancé.
\n\nExemples pratiques de Generics en JavaScript
\n\nExaminons quelques scénarios réels où les génériques sauvent vraiment la mise.
\n\n1. Fonctions génériques pour travailler avec des tableaux
\n\nSupposons que vous écriviez une utilitaire pour extraire le premier élément d'un tableau :
\n\nfunction first<T>(arr: T[]): T | undefined {\n return arr[0];\n}\n\nconst numbers = [10, 20, 30];\nconst firstNum = first(numbers); // type number | undefined\n\nconst strings = ["a", "b", "c"];\nconst firstStr = first(strings); // type string | undefined\n\n\nSans génériques, il faudrait écrire deux fonctions séparées ou utiliser any. Avec le typage JavaScript via les Generics, une seule fonction fonctionne pour tous les types.
2. Classes génériques pour le stockage de données
\n\nImaginez que vous créiez une simple enveloppe pour stocker une valeur :
\n\nclass Box<T> {\n private content: T;\n\n constructor(initial: T) {\n this.content = initial;\n }\n\n getValue(): T {\n return this.content;\n }\n\n setValue(value: T): void {\n this.content = value;\n }\n}\n\n// Utilisation\nconst numberBox