Generics et typage en JavaScript : comment écrire du code sans bugs

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi le typage est un super-pouvoir, pas un fardeau

\n\n

Imaginez : 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.

\n\n

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\n

Que sont les Generics et pourquoi en a-t-on besoin ?

\n\n

Les 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\n

Sans génériques, vous écririez quelque chose comme :

\n\n
function identity(arg: any): any {\n    return arg;\n}
\n\n

Le 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 :

\n\n
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\n

De 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.

\n\n

Generics vs any : la bataille pour la sécurité

\n\n

Beaucoup 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.

\n\n

Regardez cet exemple sans Generics :

\n\n
function 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\n

Avec les génériques, vous indiquez explicitement que la fonction travaille avec des tableaux ou des chaînes :

\n\n
function 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\n

Vous 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\n

Exemples pratiques de Generics en JavaScript

\n\n

Examinons quelques scénarios réels où les génériques sauvent vraiment la mise.

\n\n

1. Fonctions génériques pour travailler avec des tableaux

\n\n

Supposons que vous écriviez une utilitaire pour extraire le premier élément d'un tableau :

\n\n
function 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\n

Sans 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.

\n\n

2. Classes génériques pour le stockage de données

\n\n

Imaginez que vous créiez une simple enveloppe pour stocker une valeur :

\n\n
class 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                

Blogs

Book Recommendations