Écrivez des fonctions et des types réutilisables qui conservent la précision des types à chaque appel.
Ouvrir cette leçon dans KodokonVous utilisez déjà des génériques sans le savoir : string[], Promise<number>... Il est temps d'en écrire. Un générique introduit un paramètre de type, une variable remplacée par un type concret à chaque utilisation. Objectif : écrire la logique une seule fois, sans sacrifier la précision des types.
function first<T>(items: T[]): T | undefined {
return items[0];
}
const n = first([10, 20, 30]);
const s = first(["a", "b"]);Notez que vous n'avez rien précisé à l'appel : TypeScript infère T depuis l'argument. Un générique sans contrainte accepte n'importe quoi ; or, une fonction a souvent besoin d'un minimum de garanties sur ses données. Le mot-clé extends impose une forme minimale à T.
interface HasId {
id: number;
}
function findById<T extends HasId>(
items: T[],
id: number
): T | undefined {
return items.find((item) => item.id === id);
}Les types eux-mêmes peuvent être génériques. C'est le quotidien du code réseau : la structure de la réponse est stable, seul le contenu de data varie. Un seul type décrit alors toutes vos réponses d'API.
interface ApiResponse<T> {
ok: boolean;
data: T;
}
type UserResponse = ApiResponse<{ name: string }>;
const res: UserResponse = {
ok: true,
data: { name: "Ada" },
};