frontend / typescript
Fonctions typées
Explication
Ce que vous allez apprendre
- Typer les paramètres et la valeur de retour d'une fonction
- Utiliser des paramètres optionnels, des valeurs par défaut et le rest (
...args) de façon typée - Placer correctement les paramètres optionnels par rapport aux paramètres obligatoires
- Déclarer des surcharges (overloads) pour une fonction au comportement variable
- Écrire une première fonction générique simple (
<T>)
Dans quel contexte ?
Un développeur ajoute un paramètre titre?: string avant un paramètre obligatoire nom: string dans la signature d'une fonction saluer(titre?, nom). TypeScript refuse immédiatement de compiler avec une erreur claire : un paramètre optionnel ne peut jamais précéder un paramètre obligatoire, car le compilateur ne pourrait pas déterminer, lors d'un appel avec un seul argument, s'il s'agit du titre ou du nom. Cette règle, invisible en JavaScript pur, est détectée immédiatement grâce au typage des fonctions.
Typer une fonction, c'est documenter son contrat
Une fonction typée en TypeScript ne se contente pas d'exécuter du code : elle annonce explicitement ce qu'elle attend en entrée et ce qu'elle promet de retourner. Cette signature devient une documentation vivante, vérifiée automatiquement à chaque appel — impossible d'oublier un paramètre ou de se tromper de type sans que le compilateur ne le signale immédiatement.
Prérequis
Cette leçon suppose les types de base (leçon 2) acquis. Une bonne connaissance des fonctions JavaScript (paramètres par défaut, rest parameters) aide également, puisque TypeScript reprend exactement cette syntaxe en y ajoutant le typage.
Paramètres optionnels, valeurs par défaut, rest
TypeScript reprend les mécanismes de JavaScript moderne (paramètre ? optionnel, valeur par défaut, ...rest pour un nombre variable d'arguments) en les rendant tous vérifiables statiquement. Une règle simple à retenir : les paramètres optionnels doivent toujours être placés après les paramètres obligatoires.
| Mécanisme | Syntaxe | Type inféré |
|---|---|---|
| Paramètre optionnel | titre?: string | string | undefined |
| Valeur par défaut | devise: string = "EUR" | string (déduit du défaut si non annoté) |
| Rest parameter | ...valeurs: number[] | Tableau du type indiqué |
Piège fréquent
function f(titre?: string, nom: string) provoque une erreur de compilation : un paramètre optionnel ne peut jamais précéder un paramètre obligatoire. Réorganisez toujours vos paramètres pour placer les optionnels en dernier.
Les surcharges (overloads)
Certaines fonctions se comportent différemment selon le nombre ou le type de leurs arguments. Les surcharges permettent de déclarer plusieurs signatures publiques différentes pour une même fonction, tout en n'écrivant qu'une seule implémentation réelle qui doit être capable de gérer tous les cas déclarés. C'est un outil puissant, à réserver aux cas où la simplicité d'une union de paramètres ne suffit pas.
Un aperçu des génériques
Cette leçon se termine sur les fonctions génériques (<T>), qui permettent d'écrire une fonction dont le type dépend de ce qu'on lui passe en argument, sans perdre aucune précision. C'est le sujet complet de la leçon suivante : ici, retenez simplement que typage des fonctions et génériques sont deux briques qui se combinent naturellement.
Commandes & code
Fonctions typées
// Paramètres typés + retour explicite
function additionner(a: number, b: number): number {
return a + b;
}
// Paramètre optionnel (doit être après les obligatoires)
function saluer(nom: string, titre?: string): string {
return titre ? `${titre} ${nom}` : nom;
}
// Valeur par défaut : le type est inféré depuis le défaut
function creerPanier(devise: string = "EUR") {
return { devise, articles: [] as string[] };
}
// Rest parameters
function somme(...valeurs: number[]): number {
return valeurs.reduce((acc, v) => acc + v, 0);
}
// Signature de fonction via type alias (utile pour callbacks)
type Comparateur<T> = (a: T, b: T) => number;
const parOrdreCroissant: Comparateur<number> = (a, b) => a - b;
[3, 1, 2].sort(parOrdreCroissant);
// Surcharges (overloads) : plusieurs signatures publiques,
// UNE seule implémentation qui doit couvrir tous les cas
function parse(valeur: string): object;
function parse(valeur: string, brut: true): string;
function parse(valeur: string, brut?: true): object | string {
return brut ? valeur : JSON.parse(valeur);
}
const objet = parse('{"a":1}'); // typé object
const texte = parse('{"a":1}', true); // typé string
// this typé explicitement (utile pour callbacks DOM / event emitters)
interface Bouton {
libelle: string;
onClic(this: Bouton, event: MouseEvent): void;
}
const bouton: Bouton = {
libelle: "Valider",
onClic(event) {
console.log(this.libelle); // "this" est bien typé Bouton ici
},
};
// Fonctions génériques (aperçu, détaillé leçon suivante)
function premier<T>(tableau: T[]): T | undefined {
return tableau[0];
}Résumé
- Toujours typer explicitement le retour d'une fonction publique/exportée.
- Les overloads décrivent des cas d'usage précis ; l'implémentation reste générique.
this: Typeen premier paramètre type le contexte sans devenir un vrai paramètre à l'appel.
Exercices pratiques
Mission : réparer une signature qui ne compile plus
Objectif : Corriger l'ordre des paramètres d'une fonction et concevoir des overloads pour un comportement variable.
Contexte
Un collègue a écrit function saluer(titre?: string, nom: string): string { ... } avant de partir en congés. Le build refuse de compiler. Ta mission : comprendre pourquoi, corriger la signature, puis aller plus loin en donnant à une fonction parse deux comportements distincts selon ses arguments, sans dupliquer son implémentation.