TypeScript : pourquoi et comment l'adopter
TypeScript est un sur-ensemble de JavaScript qui ajoute un système de types statiques. Concrètement, vous écrivez du JavaScript, mais vous précisez la nature de vos données (texte, nombre, objet, fonction), et un vérificateur repère les erreurs avant l’exécution. Le code final reste du JavaScript classique. Ce guide explique pourquoi TypeScript s’est imposé et comment apprendre TypeScript en douceur, y compris sur un projet existant.
Le problème que TypeScript résout
En JavaScript, une variable peut tout contenir, et rien ne vous prévient si vous faites une erreur de type. Ce code s’exécute sans broncher… puis plante à l’usage :
function prix(quantite, unitaire) {
return quantite * unitaire;
}
prix("3", 10); // "30" ? NaN ? le bug passe inaperçu
TypeScript refuse ce genre de code dès l’écriture. L’erreur est signalée dans l’éditeur, pas découverte par un utilisateur en production. À cela s’ajoute une autocomplétion bien plus précise : votre éditeur connaît la forme exacte de vos données et vous guide.
Si les bases du langage ne sont pas encore solides, notre guide pour apprendre JavaScript est le point de départ idéal, car TypeScript s’appuie entièrement dessus.
Installer et lancer TypeScript
TypeScript s’installe via npm et se compile en JavaScript avec la commande tsc.
npm install -D typescript
npx tsc --init # crée le fichier de configuration tsconfig.json
npx tsc # compile les fichiers .ts en .js
Le fichier tsconfig.json centralise les options du compilateur. L’option la plus importante est strict: true, qui active toutes les vérifications rigoureuses. Activez-la : elle vous évite les mauvaises surprises.
Les types de base
L’annotation d’un type se fait avec deux-points après le nom. Souvent, TypeScript infère le type tout seul, mais l’expliciter clarifie l’intention.
let nom: string = "Coder Studio";
let age: number = 30;
let actif: boolean = true;
let tags: string[] = ["web", "dev"];
// Fonction typée : paramètres et valeur de retour
function prix(quantite: number, unitaire: number): number {
return quantite * unitaire;
}
prix("3", 10); // ❌ Erreur : "3" n'est pas un number
Deux types méritent une mention. any désactive toute vérification (à éviter, c’est revenir au JavaScript non typé), et unknown est son équivalent sûr : il vous force à vérifier le type avant de l’utiliser.
Les interfaces : décrire la forme d’un objet
Une interface définit la structure attendue d’un objet. C’est l’outil central pour modéliser vos données.
interface Utilisateur {
id: number;
nom: string;
email: string;
actif?: boolean; // le ? rend la propriété optionnelle
}
function afficher(u: Utilisateur): string {
return `${u.nom} (${u.email})`;
}
const lea: Utilisateur = { id: 1, nom: "Léa", email: "[email protected]" };
afficher(lea);
Si vous oubliez une propriété obligatoire ou vous trompez de type, TypeScript le signale immédiatement. Les interfaces se composent aussi entre elles (via extends), ce qui permet de bâtir des modèles de données précis.
Les types union
Un des mécanismes les plus utiles : une valeur peut avoir plusieurs types possibles, séparés par une barre verticale.
type Statut = "brouillon" | "publie" | "archive";
function badge(statut: Statut): string {
return statut.toUpperCase();
}
badge("publie"); // ✅
badge("supprime"); // ❌ non autorisé
Ici, Statut n’accepte que trois chaînes précises. Impossible de se tromper de valeur : une source d’erreurs entière disparaît.
Les génériques : du code réutilisable et typé
Les génériques permettent d’écrire des fonctions ou des structures qui fonctionnent avec n’importe quel type, tout en conservant la sécurité du typage. Le type est passé en paramètre, entre chevrons.
function premier<T>(liste: T[]): T | undefined {
return liste[0];
}
const n = premier<number>([1, 2, 3]); // n est de type number
const s = premier(["a", "b"]); // s est inféré : string | undefined
Le T est un type variable : il prend la forme de ce qu’on lui passe. C’est ce qui permet d’écrire une fonction générique une seule fois, tout en gardant un typage précis à chaque appel. Les bibliothèques modernes reposent massivement sur ce mécanisme.
Migrer un projet existant, progressivement
L’un des grands atouts de TypeScript est qu’on peut l’adopter par étapes, sans tout réécrire. La stratégie recommandée :
- Renommer un fichier
.jsen.ts(ou.jsxen.tsx). Comme tout JavaScript valide est du TypeScript valide, le code continue de fonctionner. - Laisser TypeScript signaler les zones floues, en commençant avec des règles souples (
strict: false). - Typer fichier par fichier, en remontant des fonctions utilitaires vers le cœur du projet.
- Durcir la configuration progressivement, jusqu’à activer
strict: true.
Cette approche incrémentale évite le chantier monolithique : chaque fichier typé est un gain immédiat, et le reste continue de tourner.
TypeScript avec React et Node
TypeScript brille particulièrement dans l’écosystème moderne. Avec React, il fiabilise les props des composants ; avec Node, il sécurise les données qui transitent par vos API. La plupart des frameworks actuels, dont Next.js, proposent TypeScript par défaut à la création du projet. Pour aller plus loin côté back-end, notre guide Node.js montre l’environnement où ce typage prend tout son sens.
Faut-il toujours adopter TypeScript ?
Pour un script jetable de quelques lignes, JavaScript suffit largement. Mais dès qu’un projet grandit, implique plusieurs personnes ou doit vivre dans le temps, TypeScript devient un allié précieux : il documente le code, prévient des classes entières de bugs et rend le refactoring bien plus serein. Le coût d’apprentissage est modeste puisque vous partez de JavaScript, et le bénéfice grandit avec la taille du projet.