Analyse statique avec ESLint et TypeScript : règles sur mesure

L'analyse statique du code est devenue un pilier du développement logiciel moderne. Elle permet de détecter les erreurs, d'imposer des conventions et de maintenir une qualité constante à mesure que les projets grossissent. En combinant la puissance du compilateur TypeScript avec la flexibilité d'ESLint, les développeurs disposent d'un duo redoutable pour explorer en profondeur la structure de leur code source et y appliquer des règles personnalisées.

ESLint excelle dans la vérification syntaxique et stylistique grâce à son architecture à base de plugins, tandis que TypeScript apporte une compréhension sémantique des types. Ensemble, ils couvrent un spectre très large : des fautes de frappe aux erreurs logiques subtiles. Cette alliance ouvre la porte à la création de règles sur mesure, capables d'encoder les bonnes pratiques spécifiques à chaque équipe ou à chaque domaine métier.

Les fondements de l'analyse statique moderne

L'analyse statique consiste à examiner le code sans l'exécuter, en s'appuyant sur des modèles formels comme l'arbre syntaxique abstrait. Chaque fichier source est transformé en une structure arborescente que les outils parcourent ensuite pour appliquer des vérifications. ESLint et TypeScript utilisent tous deux cette représentation, mais à des niveaux différents : le premier se concentre sur la syntaxe JavaScript et TypeScript, tandis que le second ajoute la compréhension des types.

Cette démarche apporte deux bénéfices majeurs. Le premier est la cohérence stylistique et architecturale au sein d'équipes parfois réparties sur plusieurs fuseaux horaires. Le second est l'automatisation de la détection de bugs qui n'apparaîtraient qu'au moment de l'exécution. Les outils contemporains vont plus loin en suggérant des corrections automatiques, ce qui accélère considérablement les revues de code et libère du temps pour les décisions à plus forte valeur ajoutée.

Mettre en place ESLint avec le parser TypeScript

La première étape pour exploiter pleinement l'analyse statique consiste à installer ESLint et son parseur dédié à TypeScript, généralement @typescript-eslint/parser. Cette combinaison permet de manipuler un AST enrichi qui conserve toutes les informations de typage. Une configuration de base se rédige dans un fichier .eslintrc.json où l'on déclare l'environnement, les extensions activées et les règles souhaitées.

Pour les projets de grande envergure, il devient vite essentiel d'exécuter ces vérifications sur des machines robustes, capables d'absorber des analyses parallèles sur des centaines de fichiers. Les développeurs qui hésitent encore sur l'infrastructure à adopter trouveront un éclairage pertinent sur la différence entre serveur dédié, VPS et cloud pour héberger leurs pipelines d'intégration continue.

Une fois l'environnement prêt, il convient d'activer les règles de base proposées par le projet @typescript-eslint/eslint-plugin. Ces règles couvrent les erreurs courantes, les bonnes pratiques de typage et les conventions stylistiques. Elles constituent un socle solide avant de se lancer dans la création de règles propres à l'organisation.

Comprendre l'AST et le modèle visiteur d'ESLint

Pour écrire une règle personnalisée, il faut d'abord saisir comment ESLint parcourt l'AST. Chaque nœud de l'arbre représente un élément du code : une déclaration de variable, un appel de fonction, une expression conditionnelle. ESLint expose un modèle visiteur dans lequel une règle définit des fonctions appelées lorsque le parcours rencontre certains types de nœuds.

Cette mécanique événementielle rappelle d'ailleurs celle des bibliothèques de programmation réactive. Pour mieux saisir la parenté entre les paradigmes de traitement de flux et la gestion d'événements asynchrones, un détour par la programmation réactive avec RxJS offre un parallèle intéressant. Les concepts d'observables et de souscription partagent une philosophie commune avec les listeners d'AST.

Côté pratique, une règle ESLint expose un objet context qui fournit plusieurs méthodes utiles : report pour signaler un problème, getSourceCode pour accéder au texte brut, ou encore getDeclaredVariables pour récupérer les liaisons symboliques. Maîtriser ces API est indispensable pour élaborer des règles précises et performantes.

Écrire une règle sur mesure pour un cas concret

Imaginons un besoin réel : interdire l'utilisation de console.log dans le code de production, mais uniquement dans les fichiers situés sous le dossier src/. Une telle règle commence par exporter un objet contenant une propriété meta (description, type, schéma) et une propriété create qui retourne les visiteurs.

Le visiteur ciblera les nœuds CallExpression dont l'argument est l'identifiant console.log. À l'intérieur, on vérifie le chemin du fichier via context.getFilename(). Si la condition est remplie, on appelle context.report avec un message explicite et, idéalement, une suggestion de correctif automatique. Cette logique simple illustre parfaitement la puissance du mécanisme d'ESLint : quelques dizaines de lignes suffisent pour transformer une convention orale en garde-fou algorithmique.

Pour aller plus loin, on peut exploiter les services TypeScript via @typescript-eslint/utils. Cela donne accès aux informations de typage, ce qui permet par exemple de détecter les variables implicitement any, les appels à des méthodes dépréciées, ou encore les comparaisons dangereuses entre types incompatibles. Les règles deviennent alors de véritables assistants architecturaux.

Stratégies de test et de déploiement des règles

Une règle non testée est une règle fragile. ESLint fournit pour cela RuleTester, un utilitaire qui prend en charge la définition de cas valides et invalides. Chaque test propose un extrait de code et le résultat attendu (aucune erreur, une erreur, plusieurs erreurs). Cette approche garantit que la règle réagit correctement aux évolutions futures du parser et aux cas limites que l'on n'avait pas anticipés.

Une fois la batterie de tests au vert, la règle peut être publiée comme un package npm autonome ou regroupée au sein d'un preset interne. La distribution via npm permet de versionner les règles, de gérer les dépendances et d'appliquer des mises à jour contrôlées. Les grandes organisations vont même jusqu'à sceller leurs règles dans des configurations partagées, imposant un standard identique à tous leurs projets.

L'écosystème évolue rapidement : nouveaux hooks, support étendu des auto-fixes, intégration avec les éditeurs via le protocole LSP. Rester à l'affût de ces avancées permet de transformer progressivement l'inspection du code en un avantage compétitif durable pour toute équipe de développement.

Pour approfondir vos pratiques d'analyse statique et découvrir comment structurer un pipeline complet autour d'ESLint et TypeScript, parcourez les tutoriels et guides détaillés disponibles sur DéveloppeurWeb. Vous y trouverez des exemples concrets, des configurations prêtes à l'emploi et des retours d'expérience pour faire passer votre code au niveau supérieur.