Accueil / Articles

Vérification contre exécution : où s’inscrit le compilateur Go de TypeScript 7 dans votre chaîne d’outils

Découvrez ce que le compilateur Go natif de TypeScript 7 accélère réellement, pourquoi des outils comme Angular et typescript-eslint sont en retard, et comment séparer la vérification de types de l’exécution.

Éditeur : REACTAPP.TOP14 min de lecture3257 mots

Sources: TypeScript 7 Moved Its Compiler to Go. Here’s What Actually Changes

TypeScript 7 remplace le compilateur auto-hébergé par une version native écrite en Go, et les chiffres présentés sont suffisamment élevés pour prêter à confusion quant à ce qui accélère réellement les choses. Votre JavaScript en production ne voit absolument pas sa vitesse changer ; en revanche, votre éditeur, les vérifications de type dans votre pipeline CI et les builds de votre monorepo le font. Parallèlement, Node, Bun et Vite ont rendu le compilateur TypeScript optionnel pour l’exécution et la transformation du code. Ce guide sépare ces aspects afin que vous puissiez décider de ce à mettre à jour, de ce à attendre, et de la manière d’organiser une chaîne d’outils où la vérification et l’exécution constituent deux tâches distinctes.

L’ampleur de TypeScript rend essentiel de bien maîtriser cette technologie. En août 2025, GitHub a indiqué que TypeScript était devenu le langage le plus utilisé par les contributeurs mensuels, devançant à la fois Python et JavaScript, avec plus de 2,6 millions de personnes qui contribuent chaque mois au code TypeScript. Tout changement dans les fondements de cet écosystème a des répercussions sur les frameworks, les linters, les gestionnaires de paquets et les éditeurs, et tous ne progressent pas au même rythme.

D’un compilateur auto-hébergé à un compilateur natif

Au préalable à la version 7, tsc était un programme auto-déployable. Son code source était en TypeScript, il était compilé en JavaScript, et ce JavaScript s’exécutait sous Node pour analyser, vérifier et gérer les projets des autres utilisateurs. L’hébergement propre est une tradition répandue pour les compilateurs, et cette conception a permis au langage de connaître une croissance explosive sur une décennie. Cependant, ses limites proviennent du runtime JavaScript : un seul thread principal, un heap géré par collecte de déchets jamais optimisé pour des graphes massifs en mémoire composés de nœuds syntaxiques et de types, ainsi que des moyens limités pour partager ces données entre les processus.

La réponse de Microsoft a été une adaptation, et non une réécriture. Le codebase en Go reflète délibérément la structure et le comportement de l’implémentation existante, de sorte que le système de types et ses sématiques doivent rester identiques. Ce qui change, c’est la base sous-jacente : du code machine natif, des threads capables de partager de la mémoire, ainsi que davantage de possibilités pour exécuter des tâches en parallèle. C’est précisément pour cette raison que Go a été un choix pragmatique ; son modèle de mémoire et son collecteur de déchets permettent à l’équipe de traduire le code existant en utilisant des structures de données similaires, plutôt que de redessiner tout le système autour de règles de propriété.

Les benchmarks publiés montrent que les compilations complètes sont désormais 8 à 12 fois plus rapides :

  • Le codebase de VS Code passe de 125,7 secondes avec TypeScript 6 à 10,6 secondes avec TypeScript 7.
  • La compilation complète de Playwright passe de 12,8 secondes à 1,47 seconde.
  • La configuration de huit travailleurs de vérification de types fait à nouveau baisser les temps d’exécution, à 7,51 secondes (VS Code) et 1,16 seconde (Playwright).
  • « TypeScript est dix fois plus rapide » est un résumé exact de ces chiffres. Il est cependant facile de se méprendre, car il ne précise pas ce qui est dix fois plus rapide.

    Qu’est-ce qui devient plus rapide, et qu’est-ce qui ne le devient pas ?

    Prenons un petit morceau de code typé ordinaire : une interface et un objet qui la respecte.

    interface User {
      id: string;
      name: string;
    }
    const user: User = {
      id: '42',
      name: 'Arthur',
    };
    

    Quelle que soit l’outil qui le compile, le navigateur ou le serveur reçoit finalement du JavaScript pur, sans les informations de type :

    const user = {
      id: '42',
      name: 'Arthur',
    };
    

    tsc en Go ne change donc rien à la vitesse d’exécution de votre application. Si une page est lente ou qu’un gestionnaire API consomme beaucoup de ressources CPU, TypeScript 7 ne modifiera pas cela.

    Les avantages se font sentir plus tôt, pendant le développement, là où TypeScript s’exécute en permanence : chargement des projets, calcul des diagnostics, affichage des complétions et de la fonction « trouver toutes les références », surveillance des fichiers, ainsi que vérification à nouveau du build dans l’environnement CI. Une mesure illustre bien cela : ouvrir un fichier contenant une erreur dans le dépôt de VS Code prenait auparavant environ 17,5 secondes avant l’apparition du premier diagnostic ; avec TypeScript 7, ce temps est inférieur à 1,3 seconde. Le nouveau serveur de langage est basé sur le Language Server Protocol, peut utiliser plusieurs threads, et Microsoft signale également beaucoup moins d’erreurs dans les commandes du serveur de langage ainsi que moins de plantages.

    La formulation utile est la suivante : l’application n’est pas plus rapide, mais le travail sur cette application l’est. Dans une grande base de code ou un monorepo, gagner quelques minutes sur chaque vérification de type et quelques secondes sur chaque diagnostic de l’éditeur modifie le cycle de feedback auquel on est confronté toute la journée. Cela représente une véritable amélioration de la productivité, même si aucun utilisateur ne s’en rendra jamais compte.

    Le reste de la version TypeScript 7

    Le compilateur natif occupe le centre de l’attention, mais plusieurs sous-systèmes ont été reconstruits autour de lui.

    Parallélisme que l’on peut ajuster

    Le parsing, l’émission des résultats et certaines parties de la vérification de type peuvent s’exécuter en parallèle, et les builds basés sur des références de projet permettent de compiler plusieurs projets en même temps, ce qui est particulièrement important dans les monorepos. Vous pouvez augmenter explicitement le nombre d’ouvriers chargés de la vérification de type :

    tsc --checkers 8
    

    Ou bien désactivez complètement le parallélisme, pour les machines ayant des ressources limitées ou lorsque vous souhaitez un comportement déterministe pendant le débogage :

    tsc --singleThreaded
    

    Un indicateur distinct --builders contrôle le nombre de compilations basées sur des références de projet qui s’exécutent en même temps. Considérez-les comme des paramètres de réglage plutôt que comme des interrupteurs permettant d’augmenter tout à l’extrême. Chaque travailleur supplémentaire occupe sa propre portion du programme en mémoire ; ainsi, un exécuteur CI doté de nombreux cœurs mais d’une RAM modeste peut finir par être plus lent, ou manquer de mémoire, si vous associez simplement les travailleurs aux cœurs. Mesurez sur vos exécuteurs réels avant de valider une configuration.

    Un mode surveillance reconstruit

    --watch a également été réimplémenté. L’équipe a d’abord essayé des approches multiplateformes plus conventionnelles disponibles dans Go, mais le sondage du système de fichiers s’est avéré trop coûteux pour les grands projets. Ils ont fini par adapter des idées du système de surveillance de fichiers en C++ de Parcel à Go et ont créé un nouveau mécanisme de surveillance visant une utilisation plus efficace des ressources sur différents systèmes d’exploitation.

    Nouveaux paramètres par défaut et options obsolètes supprimées

    TypeScript 7 conserve les modifications de configuration introduites lors de la transition vers TypeScript 6 :

    • strict est activé par défaut.
    • La valeur par défaut pour module est désormais esnext.
    • types commence par un tableau vide, ce qui signifie que les paquets de types globaux ne sont plus chargés automatiquement.
    • target: es5 a été supprimé.
    • La résolution de modules classique a également été supprimée.
  • La sortie pour les modules AMD et UMD a été supprimée.
  • baseUrl n’est plus pris en charge.
  • tsconfig.json qui n’a pas été modifié depuis l’époque où Internet Explorer posait des problèmes de déploiement nécessitera probablement des ajustements. En particulier, la modification des types peut provoquer une série d’erreurs du type « nom non trouvé » pour les variables globales de test ou les fonctions intégrées de Node, tant que vous n’avez pas listé les packages sur lesquels vous comptez. Si vous n’avez pas encore traité ces paramètres par défaut, notre guide pratique de migration vers les paramètres par défaut changeants de TypeScript 6.0 en traite en détail, et les mêmes corrections s’appliquent ici.

    L’élément manquant : une API de compilateur stable

    Le détail le plus important est quelque chose que TypeScript 7.0 ne comprend pas : une API programmative stable. Pour de nombreux projets, cela compte plus que n’importe quel paramètre ou valeur par défaut, car c’est ce qui détermine si les outils associés au compilateur peuvent fonctionner correctement.

    Pourquoi l’écosystème ne peut pas changer du jour au lendemain

    Appeler le compilateur depuis une terminal et créer un outil à partir de ce dernier représentent deux relations très différentes. De nombreux frameworks, outils linguistiques et analyseurs ne se contentent pas d’utiliser directement le binaire :

    tsc
    

    Ils chargent TypeScript en tant que bibliothèque et lui demandent des arbres syntaxiques, des types résolus, des réponses du service linguistique ainsi que d’autres informations internes au compilateur. Un remplaçant pour cette API devrait arriver avec TypeScript 7.1, et jusqu’à ce moment-là, Microsoft prend officiellement en charge l’installation simultanée des deux versions majeures. À l’heure où cet article est écrit, cela signifie que de nombreuses équipes utiliseront le compilateur natif pour les vérifications en ligne de commande, tandis que leurs intégrations d’éditeur et leurs outils de détection d’erreurs continueront à charger la version basée sur JavaScript.

    Plusieurs outils bien connus en sont affectés :

    • Vérification des types dans les templates d’Angular est fortement intégrée à TypeScript, ce qui oblige pour l’instant le support complet d’Angular dans les éditeurs à rester basé sur l’ancien service linguistique.
    • Les outils destinés à Vue, Astro, Svelte, MDX et d’autres formats qui intègrent TypeScript dans un autre type de fichier font face à des limitations similaires jusqu’à la mise à disposition de la nouvelle API.

    Rien de tout cela n’est une faille du port. C’est ainsi qu’apparaît la migration d’un outil fondamental dans un écosystème réel : le moteur est prêt avant que tout ce qui y est connecté n’ait été adapté.

    Quatre manières dont un outil peut dépendre de TypeScript

    typescript-eslint constitue un bon exemple à cet égard. ESLint lui-même n’est pas basé sur le compilateur TypeScript, donc affirmer que « ESLint est devenu plus rapide parce que TypeScript a été migré vers Go » serait simplement faux. typescript-eslint, en revanche, est le pont qui permet à ESLint d’analyser la syntaxe TypeScript et, pour les règles prenant en compte les types, d’accéder aux informations de type de TypeScript. Son analyseur actuel repose encore sur l’API du compilateur ancienne, bien que le projet ait expérimenté avec l’implémentation native. Les mainteneurs se préparent clairement, mais adopter TypeScript 7 ne relève pas simplement d’une mise à jour du numéro de version.

    Cet exemple met en évidence une distinction à garder à l’esprit chaque fois que quelqu’un affirme qu’une outil « utilise TypeScript ». Il existe au moins quatre types de relations différentes :

    • Écrit en TypeScript. Le code source de l’outil lui-même est en TypeScript. Ses mainteneurs bénéficient d’une vérification de types et d’un compilage plus rapides, mais les utilisateurs ne remarquent aucun changement.
    • Exécute TypeScript. Des environnements d’exécution comme Node et Bun acceptent des fichiers .ts en entrée sans faire appel à tsc.
    • Transforme TypeScript. Des outils de bundling et des transpilateurs suppriment les types et réécrivent la syntaxe, un fichier à la fois.
    • Dépend des sémantiques de TypeScript. Des outils de linting dotés de règles conscientes des types, ainsi que les services linguistiques et éditeurs de framework, ont besoin du compilateur pour comprendre l’ensemble d’un programme.

    Le port natif change de manière différente pour chaque catégorie. Seule la dernière nécessite l’API du compilateur, et c’est précisément cette catégorie qui doit attendre la version 7.1.

    Un gestionnaire de paquets en cours de migration

    pnpm montre comment ces catégories interagissent. Il s’agit d’un grand monorepo en TypeScript contenant de nombreux paquets, des processus CI intensifs ainsi que de nombreuses analyses effectuées par l’éditeur, ce qui en fait en théorie un bénéficiaire idéal de TypeScript 7. Cela devrait finalement être le cas. En attendant, ses mainteneurs doivent également faire fonctionner typescript-eslint, et cette intégration avec le linter reste liée à l’interface du compilateur ancienne. La chaîne de dépendances ressemble approximativement à ceci :

    pnpm
      ↓
    typescript-eslint
      ↓
    TypeScript compiler API
      ↓
    TypeScript 6 — for now
    

    Il est également utile de préciser ce que vivront les utilisateurs de pnpm. TypeScript 7 ne rend pas cette commande plus rapide :

    pnpm install
    

    L’installation des paquets fait partie du comportement en temps de exécution de pnpm, qui s’exécute sous forme de JavaScript sur Node, quel que soit le compilateur ayant vérifié son code source. Ce que TypeScript 7 peut améliorer, c’est l’expérience de développement de pnpm : la vérification de types, les exécutions en CI et d’autres workflows gérés par des compilateurs. Même cette amélioration n’intervient que au rythme du maillon le plus lent de son graphe de dépendances. Un projet de grande envergure ne peut pas adopter un changement fondamental plus rapidement que les outils sur lesquels il dépend.

    Où les gains sont immédiats

    Les projets qui n’ont besoin que du compilateur en tant qu’outil de vérification en ligne de commande et d’un serveur de langage peuvent en bénéficier immédiatement. VS Code est l’exemple le plus évident : il s’agit d’une vaste base de code TypeScript où des millions de développeurs utilisent quotidiennement les outils associés à ce langage. Réduire le temps de compilation complet de plus de deux minutes à environ dix secondes est significatif ; réduire le temps d’attente pour les premières diagnostics de l’éditeur de près de dix-sept secondes à un peu plus d’une seconde est quelque chose que tout le monde peut ressentir.

    Playwright, l’un des projets de référence de Microsoft, voit son temps de compilation complet passer de 12,8 secondes à 1,47 seconde avec la configuration par défaut. Cela ne signifie pas pour autant que Playwright lance Chromium plus rapidement ; cela signifie simplement que la maintenance et la vérification du code propre à Playwright deviennent beaucoup plus rapides. Étant donné que de nombreux outils pour développeurs sont eux-mêmes écrits en TypeScript, une maintenance plus rapide de ces outils a un effet positif sur l’ensemble de l’écosystème.

    Vite traite déjà la vérification et la transformation comme des tâches distinctes

    Vite est principalement écrit en TypeScript, mais lorsqu’il sert ou compile votre application TypeScript, il n’appelle pas le compilateur TypeScript pour transpiler chaque module. La version moderne de Vite utilise un pipeline de transformation dédié et omet intentionnellement la vérification des types. Sa documentation recommande d’exécuter TypeScript séparément, en tant que vérification ponctuelle :

    tsc --noEmit
    

    ou de manière continue pendant le développement :

    tsc --noEmit --watch
    

    La logique est solide. Pour transformer un fichier, il suffit de supprimer les annotations, de réécrire quelques constructions et d’en rester là. La vérification de type nécessite une connaissance de l’ensemble du graphe des modules, car un changement dans un fichier peut briser les contrats d’un autre. Faire les deux en même temps force l’opération rapide à attendre celle qui est lente. Un projet Vite typique dispose donc de deux chemins parallèles à partir de la même source :

    ┌── Vite / Oxc ── transform ──> Browser
    TypeScript source ──┤
                        └── TypeScript ───── type-check
    

    Vu sous cet angle, TypeScript 7 n’a pas besoin de devenir le transformateur JavaScript le plus rapide, car Vite dispose déjà d’un outil optimisé à cet effet. TypeScript peut se concentrer sur la tâche qui exige de comprendre l’ensemble du programme, et cette tâche est désormais considérablement plus rapide. Si vous utilisez cette configuration aujourd’hui, une conséquence pratique est qu’une erreur de type ne met pas en pause le serveur de développement ; assurez-vous que tsc --noEmit s’exécute dans le CI ou via un hook avant déploiement afin que les erreurs ne passent inaperçues.

    Outils JavaScript écrits en tout sauf en JavaScript

    Il existe une tendance plus large à cet égard. Le pipeline de compilation actuel de Vite utilise Rolldown, et tant Rolldown que Oxc sont écrits en Rust. esbuild a choisi Go il y a des années. Bun implémente une grande partie de ses fonctionnalités en Zig. Aujourd’hui, TypeScript rejoint ce groupe avec Go.

    Ce n’est pas une critique de JavaScript. Les interfaces publiques restent naturelles pour les développeurs JavaScript et TypeScript, tandis que le parsing, la résolution et l’analyse gourmands en ressources CPU s’exécutent sous forme de code natif. Chaque couche a des exigences différentes, et TypeScript 7 est l’exemple le plus récent de choix du langage d’implémentation par couche.

    Environnements de exécution qui gèrent TypeScript sans tsc

    Même séparation se produit du côté de l’environnement de exécution. Le modèle mental traditionnel d’un projet TypeScript était une ligne droite allant du code source au compilateur, puis à JavaScript, et enfin à Node :

    TypeScript
        ↓
       tsc
        ↓
    JavaScript
        ↓
      Node.js
    

    Les projets réels comptaient toujours plus d’étapes, mais l’idée de base restait la même : Node exécutait JavaScript, il fallait donc d’abord transformer TypeScript en JavaScript. Aujourd’hui, cela fonctionne directement :

    node server.ts
    

    Le détail important est que Node ne lance pas le compilateur TypeScript. Son support intégré est intentionnellement minimal : il supprime la syntaxe de TypeScript pouvant être éliminée et exécute ce qui reste. Il ne effectue aucune vérification de type, et la syntaxe nécessitant la génération de véritable JavaScript (plutôt que simplement la suppression des annotations) échappe à ce mécanisme de suppression. Une déclaration typée telle que celle-ci :

    const port: number = 3000;
    

    devient en fait ce qui suit avant l’exécution :

    const port = 3000;
    

    Le mot-clé est « Erasable ». Des constructions telles que enum, namespace avec des valeurs à l’exécution, ou des propriétés de paramètres de constructeur génèrent du JavaScript qui n’existait pas dans le code source, de sorte que le nettoyage pur ne peut pas les gérer. TypeScript propose l’option de compilateur erasableSyntaxOnly pour signaler de telles constructions si vous souhaitez que votre code reste compatible avec le nettoyage des types ; consultez la documentation actuelle de Node et de TypeScript pour connaître le comportement exact dans vos versions.

    Cette fonctionnalité existe déjà avant Node 26, donc l’exécution directe de TypeScript ne devrait pas être présentée comme une caractéristique spécifique à Node 26. Node 26 apporte ses propres modifications, notamment Temporal activé par défaut, un V8 plus récent, une autre mise à jour majeure d’Undici ainsi que les corrections habituelles associées à une version majeure, mais ce sont des sujets distincts. Ce qui importe pour cette discussion, c’est l’évolution : Node traite de plus en plus TypeScript comme un input qu’il peut consommer directement, sans avoir d’abord besoin que tsc génère du JavaScript.

    Bun traite TypeScript comme un input normal

    Bun, qui est encore dans sa version 1.x, fonctionne de cette manière depuis le début. Lancer un fichier TypeScript se fait simplement :

    bun server.ts
    

    Le chargeur de Bun supprime et transforme la syntaxe TypeScript avant son exécution en utilisant ses propres outils. Et, une fois de plus, le transpilation n’implique pas de vérification des types. Un flux de travail parfaitement viable avec Bun consiste donc en deux commandes :

    tsc --noEmit
    bun server.ts
    

    Le premier répond à la question « Ce programme satisfait-il le système de types ? » Le second répond « Ce programme peut-il s’exécuter ? » Node moderne prend en charge cette même séparation :

    tsc --noEmit
    node server.ts
    

    Dans les deux cas, le temps de exécution n’attend jamais le vérificateur de types, et ce dernier n’a pas besoin de générer de fichiers de sortie. Il convient de se rappeler qu’un projet géré de cette manière ne dispose d’aucune étape de compilation pour détecter par hasard des erreurs de type ; si la vérification n’est pas intégrée au CI, elle ne se produira tout simplement pas.

    La mission de TypeScript est de se concentrer sur la compréhension des programmes

    Pendant des années, le flux de travail était compressé en un seul pipeline, où le compilateur se situait directement entre l’écriture et l’exécution du code :

    Write TypeScript
          ↓
    Compile TypeScript
          ↓
    Run JavaScript
    

    Les outils modernes ressemblent de plus en plus à deux branches issues de la même source : l’une pour la compréhension et la vérification, l’autre pour la transformation et l’exécution :

    ┌── TypeScript ── understand and check
    TypeScript source ────────┤
                              └── Runtime / bundler ── transform and execute
    

    Vite peut utiliser Oxc pour transformer le code tandis que tsc le vérifie. Node supprime automatiquement la syntaxe éliminable. Bun dispose de son propre chargeur. Aucun de ces outils n’a besoin de TypeScript 7, ni d’aucun tsc, pour exécuter votre application. C’est précisément pourquoi le compilateur natif reste important : la responsabilité principale de TypeScript n’est plus de transformer rapidement un fichier .ts en fichier .js, tâche déjà bien accomplie par d’autres outils. Sa véritable valeur réside dans des questions liées à l’ensemble du programme, telles que :

    • Ce résultat est-il compatible avec le contrat auquel il est transmis ?
    • Une refonte a-t-elle endommagé un composant dans un autre package ?
    • Cette contrainte générique est-elle correcte ?
    • À quoi fait référence ce symbole, et où d’autre ce type est-il utilisé ?
    • Quelle suggestion d’completion l’éditeur devrait-il proposer ici ?

    Pour répondre à ces besoins, il faut bien plus de contexte que de simplement supprimer : string d’une ligne, et c’est l’analyse de l’ensemble du programme que la version Go rend considérablement plus rapide. Pour en savoir davantage sur l’exécution native de TypeScript à l’aide de ces outils, consultez notre guide de migration vers le compilateur Go et l’exécution native de TypeScript.

    Points clés

    • TypeScript 7 est une adaptation du compilateur existant à Go, et non une refonte du langage ; le JavaScript généré ainsi que les performances en temps de exécution de votre application restent inchangés.
    • Les avantages se font sentir pendant le développement : les compilations complètes sont généralement 8 à 12 fois plus rapides, les diagnostics dans l’éditeur sont beaucoup plus迅速, et le serveur de langage est plus stable.
  • Ajustez les paramètres --checkers, --builders et --singleThreaded en fonction des limites réelles de mémoire du CI, plutôt que d’optimiser aveuglément le nombre d’ouvriers.
  • Prévoyez une période hybride. En l’absence d’une API de compilation stable avant la version 7.1, Angular, Vue, Svelte, Astro, les outils MDX ainsi que typescript-eslint pourraient vous obliger à utiliser TypeScript 6 pour certaines intégrations, et il est possible d’exécuter les deux versions côte à côte.
  • Vérifiez le fichier tsconfig.json pour identifier les nouvelles valeurs par défaut et les options supprimées (strict, module, types, cible ES5, résolution classique, AMD/UMD, baseUrl).
  • Considérez la vérification des types comme une étape distincte. Vite, Node et Bun exécutent ou transforment le TypeScript sans le vérifier, il est donc nécessaire d’inclure tsc --noEmit dans les processus CI.