L'essentiel en une minute

Apprendre TypeScript prend peu de temps quand on connaît déjà JavaScript : c'est le même langage, avec des types vérifiés avant l'exécution. Ce guide part de là. Si les variables, les fonctions, map ou async/await ne vous sont pas encore familiers, commencez par notre guide pour apprendre JavaScript : nous ne reprenons pas ces bases ici.

Chaque exemple a été vérifié avec le compilateur TypeScript 7.0.2 et exécuté avec Node.js 22.15.0 et l'option --experimental-strip-types ; les erreurs affichées sont celles que le compilateur a produites. Versions et chiffres viennent de sources officielles lues le 31 octobre 2026.

Points clés

  • TypeScript vérifie les types avant l'exécution, puis les efface : il ne valide pas les données reçues.
  • La version courante est TypeScript 7.0.2, un compilateur natif que Microsoft annonce de 8 à 12 fois plus rapide sur une compilation complète.
  • Node.js exécute un fichier .ts sans option depuis la version 22.18.0, si le code n'utilise que de la syntaxe effaçable, et sans vérifier les types.
  • À apprendre en premier : inférence, interfaces, unions, rétrécissement, génériques, et unknown plutôt que any.
  • Un projet JavaScript se migre fichier par fichier, avec checkJs et JSDoc d'abord.

Ce que TypeScript ajoute à JavaScript, et ce qu'il ne fait pas

TypeScript est une surcouche de JavaScript : il ajoute une syntaxe de types, un vérificateur qui la contrôle avant l'exécution, et un outillage d'éditeur qui s'en sert. Le reste est du JavaScript.

Ce qu'il apporte, concrètement :

  • Des types statiques. Un appel avec une chaîne là où un number est attendu est signalé avant l'exécution.
  • Des erreurs à la compilation. Propriété mal orthographiée, valeur peut-être undefined, argument oublié : tsc les trouve sans exécuter le code.
  • Un éditeur plus utile. Autocomplétion, renommage sûr et navigation s'appuient sur les types, dans VS Code ou un autre IDE.

Ses limites sont aussi importantes à comprendre pour apprendre TypeScript sans malentendu :

  • Les types sont effacés à l'exécution. Le code n'est pas plus rapide, et rien n'est vérifié pendant qu'il tourne.
  • Aucune validation des données externes. Une requête HTTP ou un fichier JSON arrivent sans garantie ; écrire as Utilisateur ne vérifie rien.
  • any désactive tout. Une valeur any n'est plus contrôlée, et l'erreur ressort à l'exécution.

Pour les données externes, il faut une validation à l'exécution. Notre tutoriel pour créer une API REST avec Node.js et Express utilise Zod, une bibliothèque qui valide les données et dont on peut dériver les types TypeScript.

Qui utilise TypeScript ?

TypeScript est sixième de l'enquête Stack Overflow 2026, utilisé par 43,8 % des 14 099 répondants à la question sur les langages (Stack Overflow Developer Survey 2026, consulté le 31 octobre 2026). C'est un usage déclaré, pas une mesure du marché.

Selon le rapport Octoverse 2026 de GitHub, TypeScript reste le premier langage par nombre de contributeurs. De septembre 2025 à septembre 2026, il a gagné 3,62 millions de contributeurs mensuels, contre 3,23 millions pour Python et 1,82 million pour JavaScript (GitHub Octoverse 2026, 28 octobre 2026).

Pourquoi apprendre TypeScript : graphique en barres des contributeurs mensuels gagnés sur GitHub de septembre 2025 à septembre 2026, 3,62 millions pour TypeScript, 3,23 millions pour Python et 1,82 million pour JavaScript

Le rapport compte les comptes actifs chaque mois, dépôts privés inclus, et un même compte peut compter pour plusieurs langages.

TypeScript vs JavaScript : le tableau des différences

La différence entre TypeScript et JavaScript tient au moment où les erreurs de type sont détectées : avant l'exécution pour TypeScript, pendant pour JavaScript.

Critère JavaScript TypeScript
Typage Dynamique, vérifié à l'exécution Statique, vérifié avant l'exécution, puis effacé
Exécution Directe dans le navigateur et Node.js Compilé en JavaScript, ou types retirés par Node.js
Erreur "5" + 3 Silencieuse, donne "53" Signalée si un number est attendu
Validation des données externes À écrire soi-même À écrire soi-même aussi (Zod, Valibot, contrôles manuels)
Éditeur Autocomplétion approximative Autocomplétion, renommage et navigation fondés sur les types
Performances à l'exécution Référence Identiques : c'est le même JavaScript qui tourne
Projets adaptés Scripts, prototypes, petites pages Code partagé en équipe, bibliothèques, applications qui durent

TypeScript n'accélère donc pas l'exécution : il réduit les erreurs qui l'atteignent. Le chiffre de 15 % de bugs évités, souvent cité, vient d'une étude de Zheng Gao, Christian Bird et Earl T. Barr présentée à la conférence ICSE 2017. Après avoir annoté à la main le code de 400 bugs publics de projets JavaScript sur GitHub, ils estiment que TypeScript 2.0 et Flow 0.30 en détectaient chacun 60, soit 15 % (intervalle de confiance à 95 % : 11,5 % à 18,5 %) (« To Type or Not to Type », ICSE 2017, DOI 10.1109/ICSE.2017.75).

Réserves : l'étude porte sur TypeScript 2.0, ne compte que des bugs déjà publiés (ce qui, selon les auteurs, sous-estime l'effet) et mesure des bugs détectables, pas évités.

Installer TypeScript 7 et configurer tsconfig

TypeScript s'installe dans chaque projet, comme dépendance de développement. Le registre npm sert la version 7.0.2 sous l'étiquette latest (consulté le 31 octobre 2026), et le site officiel indique « currently 7.0 ».

npm install --save-dev typescript npx tsc --version # -> Version 7.0.2 npm pkg set type=module 

La dernière commande ajoute "type": "module" au package.json. Sans elle, avec la configuration ci-dessous, tsc traite vos fichiers comme du CommonJS et refuse import et export (erreurs TS1295 et TS1287 dans notre essai).

Ce qui change avec TypeScript 7

TypeScript 7 est une réécriture du compilateur en code natif. Selon son annonce, il donne « typiquement des accélérations entre 8x et 12x sur les compilations complètes » (blog de TypeScript, 8 juillet 2026, notre traduction). Ce sont des mesures de Microsoft (équipe TypeScript) ; le graphique reprend les cinq projets publiés, de 7,7x à 11,9x.

Graphique en haltères : temps de compilation complète de TypeScript 6.0 à TypeScript 7.0 selon l'équipe TypeScript, de 125,7 à 10,6 secondes pour vscode et de 139,8 à 15,7 secondes pour sentry

Trois conséquences pour qui débute en 2026 :

  • strict est activé par défaut depuis TypeScript 6.0, et module vaut esnext. Les options dépréciées en 6.0, comme target: es5 ou baseUrl, sont devenues des erreurs.
  • Le compilateur n'expose pas encore d'API programmable. Le contrôle des gabarits Vue, Svelte, Angular, Astro ou MDX n'est donc pas encore pris en charge et ces outils restent sur TypeScript 6.0. TypeScript 7.1, en bêta depuis le 20 octobre 2026, doit apporter une nouvelle API (annonce de TypeScript 7.1 Beta).
  • L'éditeur. L'annonce indique que VS Code dispose d'une extension dédiée à TypeScript 7. Pour bien équiper l'éditeur par ailleurs, voyez notre sélection d'extensions VS Code.

Le tsconfig.json essentiel

npx tsc --init génère un fichier commenté qui active notamment strict et noUncheckedIndexedAccess, et fixe "types": [] : pour Node.js, ajoutez "types": ["node"] et installez @types/node.

Voici la configuration utilisée pour nos exemples, celle que recommande la documentation de Node.js, plus strict et skipLibCheck :

{ "compilerOptions": { "target": "esnext", "module": "nodenext", "strict": true, "noEmit": true, "erasableSyntaxOnly": true, "verbatimModuleSyntax": true, "rewriteRelativeImportExtensions": true, "skipLibCheck": true } } 
Option Rôle
strict Toutes les vérifications strictes, dont noImplicitAny
noEmit Vérifie sans produire de fichiers .js
erasableSyntaxOnly Refuse la syntaxe que Node.js ne sait pas effacer, comme enum
verbatimModuleSyntax Impose import type pour les imports de types
rewriteRelativeImportExtensions Autorise les imports en .ts et les réécrit en .js lors d'une compilation

Exécuter un fichier .ts directement avec Node.js

Node.js sait retirer les annotations d'un fichier .ts et exécuter le JavaScript restant. Selon sa documentation, cette suppression des types est activée par défaut depuis les versions 23.6.0 et 22.18.0, et elle est déclarée stable depuis les versions 25.2.0 et 24.12.0 (TypeScript dans Node.js, consulté le 31 octobre 2026).

node bases.ts # Node.js 22.18.0 ou plus récent npx tsc --noEmit # la vérification des types, à lancer à part 

Quatre règles évitent les surprises :

  1. Node.js ne vérifie pas les types. Sa page d'apprentissage recommande npx tsc --noEmit à côté.
  2. Seule la syntaxe effaçable passe. enum, les propriétés de paramètres, les namespace qui contiennent du code et les alias import x = require(...) demandent une transformation. L'option --experimental-transform-types, qui contournait cette limite, a été retirée dans Node.js 26.0.0.
  3. L'extension est obligatoire dans les imports : import "./fichier.ts", pas import "./fichier".
  4. Les imports de types portent le mot-clé type, sinon le programme échoue.

Les fichiers .tsx et les paths du tsconfig ne sont pas pris en charge non plus : dans ce cas, compilez avec tsc ou un outil de build.

Apprendre TypeScript par les notions clés

Ces exemples passent tous tsc avec la configuration ci-dessus ; // -> indique la sortie obtenue. C'est l'ordre que nous conseillons pour apprendre TypeScript.

Annotations et inférence

const prenom: string = "Inès"; let score = 10; // type inféré : number const langage = "TypeScript"; // type inféré : "TypeScript" function prixTTC(prixHT: number, taux: number = 0.2): number { return prixHT * (1 + taux); } score = score + 5; console.log(`${prenom} a ${score} points`); // -> Inès a 15 points console.log(prixTTC(100), langage); // -> 120 TypeScript 

N'annotez pas tout. TypeScript déduit le type de score de sa valeur initiale. Annotez surtout les paramètres de fonctions et les valeurs de retour publiques : c'est là que les types documentent votre code.

Interfaces et alias de type

interface Utilisateur { id: number; nom: string; email?: string; // propriété facultative } interface Admin extends Utilisateur { droits: string[]; } type Point = { x: number; y: number }; const ada: Admin = { id: 1, nom: "Ada", droits: ["publier"] }; console.log(ada.nom, ada.email ?? "pas d'e-mail"); // -> Ada pas d'e-mail 

Le manuel officiel note qu'une interface peut être rouverte pour recevoir de nouvelles propriétés, pas un alias type, et propose une règle : utiliser interface jusqu'à avoir besoin d'une fonction propre à type (par exemple une union) (Everyday Types, notre traduction).

Unions, types littéraux et rétrécissement

type Role = "admin" | "editeur" | "lecteur"; // union de types littéraux function formater(valeur: string | number): string { if (typeof valeur === "number") { return valeur.toFixed(2); // ici, valeur est un number } return valeur.toUpperCase(); // ici, valeur est une string } type Resultat = | { ok: true; valeur: number } | { ok: false; erreur: string }; function afficher(r: Resultat): string { return r.ok ? `Valeur : ${r.valeur}` : `Erreur : ${r.erreur}`; } console.log(formater(3.14159), formater("ts")); // -> 3.14 TS console.log(afficher({ ok: false, erreur: "fichier introuvable" })); // -> Erreur : fichier introuvable 

Le rétrécissement (narrowing) est le cœur de TypeScript au quotidien : après un test typeof, in ou sur une propriété commune comme ok, le compilateur sait quel membre de l'union vous manipulez.

Pour qu'un switch traite tous les cas d'une union, ajoutez une vérification d'exhaustivité avec le type never :

type Forme = | { type: "cercle"; rayon: number } | { type: "carre"; cote: number }; function aire(f: Forme): number { switch (f.type) { case "cercle": return Math.PI * f.rayon ** 2; case "carre": return f.cote ** 2; default: { const jamais: never = f; // erreur si un cas est oublié return jamais; } } } console.log(aire({ type: "carre", cote: 3 }).toFixed(2)); // -> 9.00 

Si l'on ajoute { type: "triangle"; base: number; hauteur: number } à l'union sans nouveau case, tsc répond : « Impossible d'assigner le type '{ type: "triangle"; base: number; hauteur: number; }' au type 'never' » (TS2322).

Les génériques

function premier<T>(liste: T[]): T | undefined { return liste[0]; } interface Reponse<T> { statut: number; donnees: T; } const n = premier([10, 20, 30]); // number | undefined const r: Reponse<string[]> = { statut: 200, donnees: ["ok"] }; console.log(n, r.donnees.length); // -> 10 1 

Un générique est un type en paramètre. premier fonctionne pour toute liste et conserve le type de ses éléments, là où any le perdrait.

Les types utilitaires

interface Article { id: number; titre: string; contenu: string; publie: boolean } type MiseAJour = Partial<Article>; // tout devient facultatif type Apercu = Pick<Article, "id" | "titre">; // garde deux propriétés type NouvelArticle = Omit<Article, "id">; // retire id type Compteurs = Record<"vues" | "partages", number>; const apercu: Readonly<Apercu> = { id: 7, titre: "Apprendre TypeScript" }; 

Ils évitent de recopier une interface pour chaque variante. Partial sert aux mises à jour partielles d'une API, Omit aux données de création sans identifiant.

L'opérateur satisfies vérifie qu'une valeur respecte un type sans perdre le type précis de chaque propriété :

type Couleur = "rouge" | "vert" | "bleu"; const palette = { rouge: "#e11d48", vert: [34, 197, 94], } satisfies Partial<Record<Couleur, string | number[]>>; console.log(palette.rouge.toUpperCase()); // -> #E11D48 console.log(palette.vert.join(", ")); // -> 34, 197, 94 

Une clé jaune serait refusée (TS2353). Avec une simple annotation de type, palette.rouge.toUpperCase() échouerait (TS18048 et TS2339).

enum ou union de littéraux ?

Préférez une union de littéraux, ou un objet as const, à enum. Avec erasableSyntaxOnly, tsc refuse enum (erreur TS1294), et Node.js 22.15.0 échoue avec ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX : « TypeScript enum is not supported in strip-only mode ». L'alternative fonctionne partout :

const Statut = { Brouillon: "brouillon", Publie: "publie" } as const; type Statut = (typeof Statut)[keyof typeof Statut]; // "brouillon" | "publie" const s: Statut = Statut.Publie; console.log(s); // -> publie 

any ou unknown ?

any accepte tout et ne vérifie plus rien. Le code suivant passe tsc en mode strict sans la moindre erreur, puis plante :

let donnee: any = "texte"; donnee.toFixed(2); // -> TypeError: donnee.toFixed is not a function 

unknown accepte tout aussi, mais interdit de s'en servir avant de l'avoir vérifié. Appeler .toUpperCase() sur une valeur unknown produit l'erreur TS18046. Voici la bonne façon d'en sortir, avec une fonction de garde :

const brut: unknown = JSON.parse('{"nom": "Ada", "age": 36}'); function estPersonne(x: unknown): x is { nom: string; age: number } { return typeof x === "object" && x !== null && "nom" in x && typeof x.nom === "string" && "age" in x && typeof x.age === "number"; } if (estPersonne(brut)) { console.log(`${brut.nom}, ${brut.age} ans`); // -> Ada, 36 ans } 

Valider à l'exécution avec Zod

Écrire ces gardes à la main devient vite pénible. Zod décrit le schéma une fois, valide à l'exécution et fournit le type :

import * as z from "zod"; const Inscription = z.object({ email: z.email(), age: z.number().int().min(16), }); type Inscription = z.infer<typeof Inscription>; // { email: string; age: number } const recu: unknown = JSON.parse('{"email": "ada@example.com", "age": "36"}'); const resultat = Inscription.safeParse(recu); if (!resultat.success) { console.log(z.flattenError(resultat.error).fieldErrors); // -> { age: [ 'Invalid input: expected number, received string' ] } } 

Le compilateur ne pouvait pas voir que age arrivait sous forme de chaîne : seule la validation à l'exécution l'a détecté. Exemple exécuté avec Zod 4.6.7, la version servie par le registre npm le 31 octobre 2026.

Migrer un petit projet JavaScript en 4 étapes

Nous avons déroulé une migration sur un projet de deux fichiers qui calcule un panier. Le bug est classique : des frais de port lus dans un formulaire arrivent sous forme de chaîne. Fichier src/panier.js :

export function total(articles, fraisPort) { const sousTotal = articles.reduce((somme, a) => somme + a.prix * a.quantite, 0); return sousTotal + fraisPort; } 

Fichier src/main.js :

import { total } from "./panier.js"; const panier = [{ nom: "Clavier", prix: 49.9, quantite: 1 }]; const fraisSaisis = "4.90"; // valeur lue dans un champ de formulaire console.log(total(panier, fraisSaisis)); // -> 49.94.90 

Étape 1 : installer TypeScript et vérifier le JavaScript tel quel. Le package.json contient déjà "type": "module". Un tsconfig.json avec "allowJs": true, "checkJs": true, "noEmit": true et "strict": false fait analyser les fichiers .js sans les modifier. Sur ce projet, npx tsc ne signale rien : sans annotations, le compilateur ne sait pas ce que fraisPort doit contenir.

Étape 2 : ajouter des types en JSDoc. Les commentaires JSDoc donnent des types sans changer d'extension :

/** * @typedef {{ nom: string, prix: number, quantite: number }} Article * @param {Article[]} articles * @param {number} fraisPort * @returns {number} *...
Source:https://dev.to/neurau_tech/apprendre-typescript-en-2026-les-bases-la-difference-avec-javascript-et-la-migration-pas-a-pas-1ejo