Générique en TypeScript : une fonction qui conserve le type reçu

Un générique laisse le type en paramètre pour qu'une fonction rende ce qu'elle a reçu : inférence, contrainte extends keyof et génériques natifs.
3 min de lecture
Believemy logo

Écrire une fonction qui rend le premier élément d'un tableau prend une ligne. La rendre utile pour des nombres comme pour des factures, sans perdre le type au passage, demande autre chose.

C'est le rôle du générique : laisser le type en paramètre, et le récupérer à l'appel.


Définition

Un générique est un paramètre de type. Il se déclare entre chevrons, à côté du nom de la fonction, et se comporte comme une variable dont la valeur est un type, fixée au moment de l'appel.

JAVASCRIPT
function premier<T>(liste: T[]): T | undefined {
  return liste[0];
}

const n = premier([1, 2, 3]);     // number | undefined
const s = premier(["a", "b"]);    // string | undefined

Personne n'a écrit premier<number> : le compilateur déduit T de l'argument reçu. Sans générique, il aurait fallu annoter le retour en any, et toute la chaîne de vérification serait tombée après cet appel.


Contraindre le paramètre de type

Un T libre n'autorise aucune opération, puisqu'il peut tout valoir. Le mot-clé extends restreint l'ensemble des types acceptés, et débloque au passage ce qui devient sûr.

JAVASCRIPT
function parCle<T, K extends keyof T>(objet: T, cle: K): T[K] {
  return objet[cle];
}

const facture = { id: 42, montant: 19 };
const m = parCle(facture, "montant");   // number
parCle(facture, "client");
// Argument of type '"client"' is not assignable
// to parameter of type '"id" | "montant"'.

Deux paramètres de type suffisent ici à décrire une règle que le langage seul ne sait pas exprimer : la clé demandée existe sur l'objet, et le retour est du type de cette clé précise.


Les génériques déjà présents partout

ÉcritureCe que le paramètre désigne
Array<T>Le type des éléments d'un Array (tableau)
Promise<T>La valeur que rendra une Promise tenue
Map<K, V>Le type des clés puis celui des valeurs d'une Map
Record<K, V>Un objet dont les clés et les valeurs sont annoncées
Partial<T>Le même type, toutes propriétés devenues facultatives
Bon à savoir

Ces cinq écritures se croisent dès la première heure de TypeScript. Comprendre le générique, c'est surtout cesser de les lire comme une syntaxe magique.


Questions fréquentes

Question

Pourquoi ne pas simplement écrire any ?

Parce que any éteint la vérification au lieu de la propager. Une fonction qui reçoit any et rend any laisse passer n'importe quelle faute de frappe en aval. Le générique, lui, conserve le lien entre ce qui entre et ce qui sort, ce qui est précisément l'information utile.


Question

Combien de paramètres de type sont raisonnables ?

Un dans la grande majorité des cas, deux quand une correspondance est en jeu, comme une clé et sa valeur. Au-delà de trois, la signature devient plus difficile à lire que le problème qu'elle résout, et une interface nommée fait presque toujours mieux.


Question

Faut-il préciser le type à chaque appel ?

Rarement. L'inférence couvre la plupart des situations, et un type écrit à la main entre chevrons signale souvent que la signature manque de contrainte. Le cas légitime reste l'appel sans argument porteur d'information, par exemple une requête dont seul le retour est typé.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.