Transformer une base de code legacy en TypeScript sans bloquer les releases ressemble parfois à un numéro d’équilibriste : il faut avancer, sécuriser, et surtout ne pas casser la production. J’ai mené plusieurs migrations progressives ces dernières années, et j’aime partager les étapes concrètes qui m’ont permis de garder les équipes productives tout en augmentant progressivement la qualité du code.
Pourquoi migrer vers TypeScript progressivement ?
TypeScript apporte un filet de sécurité très utile : typage statique, meilleure autocomplétion, refactorings plus fiables. Mais dans un projet existant, une migration « tout ou rien » est rarement réaliste — elle bloque les releases, fatigue l’équipe et génère de la dette temporaire. À la place, je privilégie une approche incrémentale qui permet de livrer des fonctionnalités en continu tout en refactorant par petits pas.
Principes que j’applique systématiquement
Étape 0 — Préparation et audit
Avant de toucher au code, je réalise un audit rapide : volume de fichiers JavaScript, complexité du build, dépendances problématiques, et tests existants. J’aime cartographier les « zones chaudes » : modules avec beaucoup de dépendances ou code fragile. Ces zones ne sont pas nécessairement les premières à migrer.
Checklist d’audit :
Étape 1 — Installer TypeScript sans forcer la compilation totale
Installer TypeScript et configurer tsconfig.json en mode permissif. Mon trick : commencer avec allowJs à true et checkJs à false, ainsi les fichiers .js continuent d’être exécutés et on peut ajouter progressivement des fichiers .ts.
| compilerOptions | { "target": "ES2019", "module": "commonjs", "allowJs": true, "checkJs": false, "outDir": "./dist", "noEmit": false, "skipLibCheck": true } |
Objectif : que le build CI ne fasse pas échouer les pipelines dès l’ajout de TypeScript. Je fais tourner la compilation TypeScript localement mais sans l’intégrer comme gate strict en CI au début.
Étape 2 — Ajouter des règles de lint progressivement
Le linting est mon allié : il guide les bonnes pratiques sans imposer le typage immédiatement. J’ajoute ESLint et le plugin TypeScript mais je n’active les règles sévères qu’après avoir stabilisé la base.
Étape 3 — Migrer par domaine fonctionnel ou par package
Plutôt que de convertir des fichiers au hasard, je choisis une zone logique — par exemple l’API client, puis les utilitaires, puis les composants UI. Pour un monorepo, migrer package par package est encore plus pratique : chaque package peut devenir un module TypeScript avec sa propre configuration.
Étape 4 — Utiliser JSDoc et checkJs comme transition
Quand convertir tous les fichiers en .ts est coûteux, j’utilise JSDoc dans les .js et active checkJs progressivement. Cela offre des bénéfices du typage (détection d’erreurs) sans renommer les fichiers tout de suite.
Étape 5 — Mettre en place des builds de type incrémental et des tests automatisés
Le secret pour ne pas bloquer les releases, c’est d’isoler la compilation TypeScript et d’en faire une étape non bloquante au début. J’ajoute un job CI qui compile mais ne bloque pas la merge. Une fois que la compilation est stable, j’augmente son importance.
Étape 6 — Gérer les types tiers et solutions pratiques
Les dépendances sans types sont souvent le frein. Pour ces cas, j’utilise plusieurs tactiques :
Exemple : au lieu d’utiliser directement un utilitaire non-typé, je crée un fichier lib/wrapper.ts avec une signature claire. Ainsi le reste de l’appli gagne en sécurité sans devoir typiser la dépendance entière.
Étape 7 — Stratégie de commit et branches
Pour éviter le chaos, je recommande des PRs petites et ciblées. Chaque PR migrera un dossier, ajoutera des types et adaptera les tests.
Étape 8 — Monter progressivement l’exigence de typage
Une fois qu’une part significative du code est en TypeScript et stable, j’augmente les règles de tsconfig : activer noImplicitAny, strictNullChecks, et réduire skipLibCheck si possible. Je fais cela dossier par dossier.
Outils et patterns que j’utilise
Un dernier conseil pratique : mesurez le progrès. J’utilise des métriques simples — pourcentage de fichiers .ts, nombre d’erreurs TypeScript en CI, couverture de tests — pour suivre la migration et ajuster la cadence sans paniquer l’équipe.