Aller au contenu

TypeScript : dépannage et migration

src/clients.ts(14,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Partie Sens
src/clients.ts(14,9) Fichier, ligne, colonne
TS2322 Code d’erreur (chercher « TS2322 » dans la documentation)
Premier message Ce qui ne va pas
Lignes indentées La cause, de la plus générale à la plus précise : lire la dernière en premier

Pour les messages très longs, décomposer le type concerné en alias nommés.

Fenêtre de terminal
npx tsc --version
npx tsc --noEmit # toutes les erreurs
npx tsc --noEmit --pretty false | head # format brut
npx tsc --showConfig
npx tsc --explainFiles | grep -i monfichier
npx tsc --noEmit --extendedDiagnostics # temps de compilation

Redémarrer le serveur de langage de l’éditeur (VS Code : « TypeScript : Redémarrer le serveur TS ») règle beaucoup d’affichages obsolètes.

Code Message Cause et solution
TS2322 Type 'X' is not assignable to type 'Y' Valeur incompatible : corriger la valeur ou le type ; undefined oublié
TS2339 Property 'x' does not exist on type 'Y' Propriété inexistante, faute de frappe, type trop large (union non affinée)
TS2345 Argument of type 'X' is not assignable to parameter of type 'Y' Argument de mauvais type ; vérifier la signature
TS2532 / TS18048 Object is possibly 'undefined' Valeur facultative : ?., ??, if
TS2531 / TS18047 Object is possibly 'null' Idem avec null
TS7006 Parameter 'x' implicitly has an 'any' type Annoter le paramètre
TS7053 Element implicitly has an 'any' type because expression of type 'string' can't be used to index Indexation par string : Record<string, …> ou keyof
TS2304 Cannot find name 'x' Import manquant, lib sans dom, @types/node absent
TS2307 Cannot find module 'x' Chemin, extension (.js avec NodeNext), moduleResolution, paquet non installé
TS7016 Could not find a declaration file for module 'x' npm install -D @types/x ou declare module 'x'
TS2554 Expected N arguments, but got M Nombre d’arguments incorrect
TS2769 No overload matches this call Aucune signature ne convient : lire la dernière ligne du détail
TS2741 Property 'x' is missing in type Propriété obligatoire absente
TS2353 Object literal may only specify known properties Propriété inconnue (faute de frappe)
TS2564 Property 'x' has no initializer and is not definitely assigned in the constructor Initialiser dans le constructeur ou à la déclaration (voir POO : classes et objets)
TS2416 / TS4114 Signature de méthode incompatible avec la classe parente / override obligatoire Corriger la signature ; noImplicitOverride impose override
TS1259 / TS1192 Problèmes de import par défaut esModuleInterop / import x = require(...) selon le module
TS2589 Type instantiation is excessively deep Types récursifs ou conditionnels trop complexes
TS5097 An import path can only end with a '.ts' extension when allowImportingTsExtensions is enabled Voir Modules et tsconfig
// @ts-expect-error : l'API renvoie ici un type non documenté (ticket #42)
const valeur: number = fonctionMalTypee();
// @ts-ignore (à éviter : ne signale pas quand l'erreur disparaît)
Commentaire Comportement
// @ts-expect-error Supprime l’erreur et échoue si l’erreur disparaît : à préférer
// @ts-ignore Supprime sans contrôle
// @ts-nocheck Désactive la vérification du fichier entier
as unknown as T Force un type (dangereux)

Toujours expliquer pourquoi. Un as any ou un @ts-ignore est un emprunt : lister ces exceptions et les résorber.

Fenêtre de terminal
grep -rnE "@ts-(ignore|nocheck|expect-error)|as any" src/ | wc -l # dette à surveiller

Migration progressive, fichier par fichier :

  1. npm install -D typescript @types/node, créer tsconfig.json avec allowJs: true, checkJs: false.
  2. Ajouter // @ts-check en tête des fichiers JavaScript pour les vérifier un par un (types décrits avec JSDoc).
  3. Renommer les fichiers .js en .ts un par un (en commençant par les feuilles : modules qui n’importent rien du projet).
  4. Typer les frontières d’abord : entrées et sorties des fonctions exportées, structures de données principales.
  5. Activer strict par morceaux (strictNullChecks d’abord, puis noImplicitAny) ou directement si le projet est petit.
  6. Ajouter tsc --noEmit à l’intégration continue dès le début, avec un seuil d’erreurs qui ne fait que baisser.
// @ts-check
/**
* @param {string} nom
* @param {number} [age]
* @returns {{ nom: string, age: number }}
*/
export function creerClient(nom, age = 0) {
return { nom, age };
}

Les annotations JSDoc permettent de typer du JavaScript sans le renommer.

Fenêtre de terminal
npm outdated typescript
npm install -D typescript@latest
npx tsc --noEmit
  1. Lire les notes de version (« Release Notes » sur typescriptlang.org) : les versions majeures et mineures peuvent durcir des vérifications et faire apparaître de nouvelles erreurs légitimes.
  2. Mettre à jour typescript-eslint et les outils de génération de types ensemble.
  3. Corriger les erreurs, ou les traiter une par une avec @ts-expect-error documenté.
  4. Vérifier que les outils (ESLint, Vite, Astro) acceptent la nouvelle version : ils déclarent la plage de versions prises en charge.

Une option de tsconfig.json dépréciée ou retirée fait échouer la compilation avec un message qui nomme l’option : lire le message, la remplacer.

Symptôme Piste
tsc lent skipLibCheck: true, incremental: true, limiter include, références de projets
Éditeur qui se fige Types très complexes (conditionnels profonds, grandes unions) : simplifier ; redémarrer le serveur TS
Mémoire élevée NODE_OPTIONS=--max-old-space-size=4096 npx tsc
Compilation incrémentale cassée Supprimer *.tsbuildinfo
Fenêtre de terminal
npx tsc --noEmit --generateTrace trace/ # trace de performance (analysable)

Un programme qui plante malgré une compilation sans erreur révèle un type faux :

Cause Prévention
as Client sur une donnée externe Validation à l’exécution (Zod)
any qui se propage no-explicit-any et no-unsafe-* d’ESLint
! (non-null) sur une valeur absente Interdire (no-non-null-assertion)
Types d’une bibliothèque obsolètes Aligner @types/… sur la version du paquet
Tableau vide typé never[] Annoter (const liste: Client[] = [])

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune propre à Ubuntu. Sous Linux, une importation dont la casse diffère du nom de fichier échoue ; vérifier aussi l’accès aux fichiers (droits) quand tsc ne trouve pas un fichier.