Réusinage de code legacy en TypeScript : de A à Z
Travailler avec du code legacy (hérité) est une réalité inévitable pour de nombreux développeurs. Ces projets sont souvent écrits en JavaScript "pur" sans types, contiennent des dépendances complexes et manquent de tests. TypeScript offre une boîte à outils puissante pour améliorer progressivement ce code, le rendant plus sûr, plus lisible et plus maintenable. Dans cet article, nous parcourrons le chemin allant de l'analyse du code ancien à la création d'une architecture propre et typée.
1. Préparation et stratégie : par où commencer ?
Avant de modifier le code, il est nécessaire de créer un "filet de sécurité". La règle d'or du réusinage : ne casse pas ce qui fonctionne. Commencez par configurer l'environnement.
1.1. Initialisation de TypeScript et mode strict
Installez TypeScript et créez un fichier de configuration tsconfig.json. Dans un premier temps, vous pouvez désactiver les vérifications strictes pour ne pas vous noyer dans les erreurs, mais vous devrez les activer progressivement.
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, // Commencez par false, puis activez progressivement "noImplicitAny": true, "strictNullChecks": true, "outDir": "./dist", "rootDir": "./src", "allowJs": true, // Permet de mélanger JS et TS "checkJs": false // Ne vérifie pas encore les fichiers JS }, "include": ["src/**/*"]}1.2. Automatisation et tests
Ajoutez un linter (ESLint) et un formateur (Prettier). S'il n'y a pas de tests, écrivez au moins des tests d'intégration pour les parties critiques. C'est votre assurance contre les régressions.
- ESLint avec le plugin TypeScript détectera les erreurs logiques.
- Jest ou Vitest pour les tests unitaires.
- Configurez des hooks pre-commit (Husky) pour que le code soit vérifié avant chaque commit.
2. Migration pas à pas : de JS à TS
N'essayez pas de tout réécrire d'un coup. Utilisez une approche itérative. Le meilleur outil ici est allowJs: true dans tsconfig. Cela permet d'inclure des fichiers JavaScript depuis TypeScript.
2.1. Renommage des fichiers et typage de base
Commencez par renommer les fichiers les plus simples comme utils.js ou helpers.js en .ts. Le compilateur commencera à signaler les any implicites. Votre tâche est de décrire les signatures des fonctions.
Avant (JavaScript) :
function calculateDiscount(price, percent) { return price - (price * percent / 100);}Après (TypeScript) :
function calculateDiscount(price: number, percent: number): number { return price - (price * percent / 100);}2.2. Travail avec "any" et "unknown"
Dans le code legacy, il y a beaucoup de any implicites. N'essayez pas de tout typer parfaitement immédiatement. Utilisez any comme solution temporaire, mais marquez-le avec un TODO. Pour les données provenant de sources externes (API, localStorage), il est préférable d'utiliser unknown avec une vérification de type ultérieure.
// Solution temporairefunction processData(data: any) { // TODO: Ajouter le type correct console.log(data.name);}
// Approche correcte pour les données externesfunction processUserData(data: unknown) { if (typeof data === 'object' && data !== null && 'id' in data) { const user = data as { id: number; name: string }; console.log(user.name); }}3. Réusinage des constructions complexes
Une fois le typage de base effectué, passez à l'amélioration de l'architecture. Le code legacy souffre souvent d'"objets divins" et de chaînes d'appels complexes.
3.1. Extraction des interfaces et des types
Au lieu de passer des objets avec une structure inconnue, créez des interfaces. Cela rend le code auto-documenté.
// Mauvaisfunction saveUser(user: any) { // On ne sait pas quels champs user possède}
// Bo