TypeScript : les bases du typage
Sommaire
Ce premier module pose les fondations du typage TypeScript : annoter une variable, comprendre ce que le compilateur devine tout seul, et distinguer les valeurs dont le type est incertain de celles qui n’existent tout simplement pas.
Objectifs#
Objectifs
- Annoter explicitement des variables avec les types primitifs
- Comprendre l’inférence de type et quand s’appuyer dessus
- Distinguer
anyetunknown - Gérer
nulletundefinedavecstrictNullChecks
Annotations et types primitifs#
Une annotation de type s’écrit après le nom de la variable, précédée de deux-points : nom: type. Les trois types primitifs les plus courants sont string, number et boolean. Une fois une variable annotée, toute affectation d’une valeur d’un autre type devient une erreur de compilation, détectée avant même l’exécution du code.
let titre: string = "Voyage à Lisbonne";
let annee: number = 2026;
let estConfirme: boolean = true;
// Erreur : le type ne correspond pas à l'annotation
// titre = 2026;Inférence de type#
TypeScript n’exige pas toujours une annotation explicite : quand une variable est initialisée immédiatement, il déduit (infère) son type à partir de la valeur assignée. Cette inférence est aussi stricte qu’une annotation manuelle, toute réaffectation d’un type différent reste une erreur. Annoter explicitement garde son intérêt quand la valeur n’est pas connue tout de suite, mais devient souvent superflu dans le cas contraire.
let ville = "Porto"; // TypeScript infère : string
// ville = 42; // Erreur : number n'est pas assignable à stringany et unknown#
any désactive complètement la vérification de type : on peut appeler n’importe quelle méthode sur une valeur any sans que TypeScript ne proteste, même si elle n’existe pas. unknown est plus sûr : il accepte lui aussi n’importe quelle valeur, mais interdit toute utilisation tant que le type n’a pas été vérifié (avec typeof, instanceof, etc.). C’est le choix recommandé pour représenter une donnée externe dont le type n’est pas garanti à l’avance, par exemple la réponse d’une API.
function traiterDonneeExterne(donnee: unknown) {
// donnee.toUpperCase(); // Erreur : le type n'est pas encore vérifié
if (typeof donnee === "string") {
console.log(donnee.toUpperCase()); // OK : TypeScript sait que c'est une string ici
}
}Attention
any n’est jamais une solution de facilité sans coût : il désactive la vérification de type sur toute la chaîne d’utilisation de la variable, pas seulement à l’endroit où il est déclaré.
null, undefined et exhaustivité#
Avec strictNullChecks (inclus dans strict: true), null et undefined ne sont plus acceptés automatiquement partout. Une variable de type string ne peut pas valoir null, sauf si on l’autorise explicitement avec une union : string | null.
function afficherEmail(email: string | null): void {
if (email !== null) {
console.log(email.toUpperCase());
} else {
console.log("Pas d'email renseigné");
}
}Un type littéral restreint une valeur à un ensemble précis, par exemple "pending" | "shipped" | "delivered" au lieu de string, ce qui permet à TypeScript de détecter une valeur invalide dès la compilation. Le type never représente une valeur qui ne peut jamais se produire : il sert notamment dans une branche default finale d’un switch, pour vérifier qu’aucun cas de l’union n’a été oublié.
type Statut = "pending" | "shipped" | "delivered";
function decrireStatut(statut: Statut): string {
switch (statut) {
case "pending":
return "En attente";
case "shipped":
return "Expédiée";
case "delivered":
return "Livrée";
default: {
const casImpossible: never = statut;
return casImpossible;
}
}
}Astuce
Si une nouvelle valeur est ajoutée à l’union Statut sans mettre à jour le switch, la branche default ne compile plus : never transforme un oubli en erreur détectée immédiatement, plutôt qu’en bug découvert à l’exécution.