# Pourquoi Microsoft a porté le compilateur TypeScript en Go plutôt qu'en Rust

> TypeScript 7.0 est sorti le 8 juillet 2026 avec un compilateur natif écrit en Go. L'architecte de C# a choisi le langage d'un autre, et la raison principale n'est pas la vitesse. Elle dit beaucoup de ce qu'est Go, y compris de ce qu'il n'est pas.


*Ou : Comment l'architecte de C# a choisi le langage d'un autre, pour une raison qui n'a presque rien à voir avec la vitesse*

Depuis le 8 juillet 2026, `npm install -D typescript` installe un compilateur qui n'est plus écrit en TypeScript. TypeScript 7.0 est un portage natif en Go, et Microsoft annonce des compilations complètes « between 8x and 12x » plus rapides[^1]. Le chiffre fait les titres. La partie intéressante est ailleurs : l'équipe dont fait partie Anders Hejlsberg, architecte principal de C#, a évalué plusieurs langages, a écrit des prototypes, y compris en C#, et a retenu Go. La raison principale n'est pas que Go serait plus rapide que Rust. C'est que le code du compilateur ressemblait déjà à du Go.

Pour un développeur Go, c'est un compliment. C'est aussi une description assez exacte de ce qu'est le langage, et de ce qu'il n'est pas.

## TypeScript 7 en Go : ce que le portage du compilateur dit du langage
{.subtitle}

### Un portage, pas une réécriture

Le 5 mars 2025, Ryan Cavanaugh, de l'équipe TypeScript, a ouvert sur GitHub une discussion intitulée sobrement « Why Go? »[^2]. Elle commence par désamorcer le débat : « many languages would be suitable in a ground-up rewrite situation ». Puis elle pose le critère qui a tout décidé : « By far the most important aspect is that we need to keep the new codebase as compatible as possible, both in terms of semantics and in terms of code structure. »

L'équipe allait maintenir deux compilateurs en parallèle, l'ancien en JavaScript et le nouveau, pendant longtemps. Chaque correctif écrit dans l'un devait pouvoir passer dans l'autre sans être repensé. Il fallait donc un langage dans lequel on traduit, et pas un langage dans lequel on reconçoit. « Idiomatic Go strongly resembles the existing coding patterns of the TypeScript codebase », conclut le texte.

Hejlsberg l'a dit plus crûment six jours plus tard, dans la même discussion, pour répondre à ceux qui demandaient pourquoi pas C# : le code existant représentait « 100 man-years of investment », et il est « all functions and data structures - no classes »[^3]. Un compilateur fait de fonctions et de structures, sans hiérarchie de classes, se traduit presque ligne à ligne en Go. On devine l'alternative en C# : écrire du C# peu idiomatique, ou réorganiser le code autour de classes. Hejlsberg le reconnaît sans détour : refaire le compilateur en C# depuis zéro « would have worked ». Mais ce n'était pas le projet.

### Le ramasse-miettes, cet atout inattendu

Le deuxième argument surprend davantage. Dans un projet où la vitesse est le but, on s'attend à voir le ramasse-miettes classé parmi les coûts. Le texte de Cavanaugh le range parmi les avantages. Go offre « excellent control of memory layout and allocation » sans obliger tout le code à se préoccuper de la gestion de la mémoire. Et le prix du ramasse-miettes est faible dans ce cas précis : une compilation n'a pas de contrainte de latence, et « Batch compilations can effectively forego garbage collection entirely, since the process terminates at the end ».

La même discussion écarte les langages qui exigent de repenser « memory management, mutation, data structuring, polymorphism, laziness ». Elle ne nomme pas Rust, elle n'en a pas besoin. Un compilateur passe son temps à parcourir des arbres de nœuds polymorphes, vers le bas et vers le haut, et le texte insiste sur ce point. Remonter vers le parent, c'est tenir une référence qui pointe dans l'autre sens, donc des cycles. En Go, c'est un pointeur. En Rust, c'est une négociation avec le vérificateur d'emprunts, ou une refonte des structures de données. Pour une réécriture, la négociation peut valoir la peine. Pour un portage, elle aurait tout changé.

**DevOps Dave :** Microsoft a choisi Go plutôt que Rust. Donc Go est plus rapide que Rust.

**Security Sarah :** Microsoft a choisi Go parce que son code ressemblait déjà à du Go.

**DevOps Dave :** Donc la leçon, c'est quoi ?

**Security Sarah :** Que le meilleur langage pour une migration est souvent celui qui ressemble le plus à ce que tu as déjà. Et que la vitesse vient surtout du fait de quitter JavaScript.

### Dix fois plus rapide, et ce que j'ai mesuré

Le gain annoncé tient en deux sources. Le code natif, d'abord, qui ne passe plus par un moteur JavaScript. La concurrence ensuite : TypeScript 7 apporte « shared memory multithreading », analyse et produit les fichiers en parallèle, et répartit la vérification des types entre quatre vérificateurs par défaut, réglables avec l'option `--checkers`[^1]. Les goroutines et la mémoire partagée font ici exactement ce pour quoi elles existent, avec les [courses de données que suppose toute mémoire partagée](/blog/concurrence-race-conditions-go/), que l'équipe a dû rendre déterministes : à fichiers identiques, la répartition entre vérificateurs est toujours la même.

Les chiffres de Microsoft portent sur de très gros projets : la compilation de VS Code passe de 125,7 à 10,6 secondes, soit 11,9 fois plus vite, et celle de Playwright de 12,8 à 1,47 seconde. J'ai voulu voir ce que ça donne sur un projet de taille ordinaire, en [mesurant plutôt qu'en croyant](/blog/benchmarks-profiling-go/) : les sources de la bibliothèque zod, 125 fichiers et environ 37 700 lignes, vérifiées par TypeScript 6.0.3 puis 7.0.2, sans erreur dans les deux cas[^4].

| Compilateur | Temps total (médiane de 10 passes) | Mémoire |
|---|---|---|
| TypeScript 6.0.3 | 3,7 s | 396 Mo |
| TypeScript 7.0.2, `--singleThreaded` | 1,16 s | non mesuré |
| TypeScript 7.0.2, réglages par défaut | 0,76 s | 284 Mo |

Environ cinq fois plus rapide, donc, et pas dix. Le code natif seul, en mode monothread, fait à peu près trois fois mieux ; le parallélisme ajoute un facteur 1,5. Sur un petit projet, il y a moins de travail à répartir entre les cœurs, et le gain du parallélisme se tasse. Les dix fois annoncés sont un chiffre de grands dépôts, honnêtement présenté comme tel. Cinq fois sur un projet moyen, ce n'est pas une déception : c'est la différence entre attendre la vérification des types et ne plus la remarquer.

### Ce que Go coûte

La discussion « Why Go? » a la franchise de lister un point faible : « Go's in-proc JS interop story is not as good as some of its alternatives ». Un compilateur écrit en JavaScript se laissait appeler, inspecter et modifier par n'importe quel outil JavaScript du même processus. Un binaire Go, non. La conséquence est visible dans TypeScript 7.0 : il « does not ship with an API »[^1]. L'équipe dit attendre une nouvelle interface de programmation, différente de l'ancienne, avec la version 7.1. D'ici là, les outils qui embarquent le compilateur, comme ceux de Vue, Astro, Svelte ou MDX, restent sur TypeScript 6.0, que Microsoft distribue à côté sous le nom `tsc6` pour que les deux versions cohabitent.

Un dernier détail de l'annonce vaut le détour. Pour surveiller les fichiers modifiés, l'équipe a regardé du côté de `@parcel/watcher`, un module écrit en C++ qui exige toute une chaîne de compilation C++. Elle l'a porté en Go, « with a few minimal assembly shims to avoid introducing a new toolchain dependency ». Une seule chaîne de compilation, un binaire par plateforme : c'est l'autre argument de Go, celui qu'aucun banc d'essai ne mesure et que toutes les équipes qui distribuent un outil finissent par apprécier.

### Ce que ça dit de Go

Go n'a pas gagné parce qu'il est le langage le plus rapide, ni le plus sûr, ni le plus expressif. Il a gagné parce qu'on peut y traduire un programme existant presque ligne à ligne, et obtenir en échange du code natif, un ramasse-miettes qui ne gêne pas, de la concurrence à mémoire partagée et un binaire sans dépendances. Autrement dit, parce qu'il est ennuyeux, au sens le plus flatteur du terme. Hejlsberg a conclu son message par une phrase qui résume assez bien le pragmatisme de l'affaire : « And you can't argue with a 10x outcome! »[^3]

Pour qui écrit du Go tous les jours, il y a quelque chose de savoureux à voir l'architecte de C# choisir ce langage pour son autre langage. Et quelque chose de rassurant à constater que la raison tient en une phrase que n'importe quel développeur Go aurait pu écrire : ton code ressemblait déjà à du Go, tu ne le savais pas encore.

---

[^1]: L'[annonce de TypeScript 7.0](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/), publiée le 8 juillet 2026 par Daniel Rosenwasser, détaille le portage « done as faithfully as possible », le tableau des temps de compilation (VS Code, Sentry, Bluesky, Playwright, tldraw, mesurés avec quatre vérificateurs) et des mémoires, l'absence d'API et le paquet de compatibilité `@typescript/typescript6`. Le portage avait été annoncé le 11 mars 2025 par Anders Hejlsberg dans [« A 10x Faster TypeScript »](https://devblogs.microsoft.com/typescript/typescript-native-port/), qui donnait déjà 77,8 secondes contre 7,5 pour VS Code.

[^2]: La [discussion « Why Go? »](https://github.com/microsoft/typescript-go/discussions/411), ouverte par Ryan Cavanaugh le 5 mars 2025 sur le dépôt `microsoft/typescript-go`, est le texte de référence. Toutes les citations de cette section en viennent. Elle mentionne aussi les prototypes écrits dans plusieurs langages et l'étude des analyseurs natifs existants, swc, oxc et esbuild.

[^3]: Le [message d'Anders Hejlsberg du 11 mars 2025](https://github.com/microsoft/typescript-go/discussions/411#discussioncomment-12466988), dans la même discussion, précise que l'équipe a écrit plusieurs prototypes, « including in C# », et rappelle que C# reste de loin le langage le plus utilisé en interne chez Microsoft. Le message tient visiblement à ce que personne n'en doute.

[^4]: Mesure faite le 4 octobre 2026 sur un portable AMD Ryzen 7 5800H (8 cœurs, 16 fils d'exécution, 23 Go de mémoire), Node.js 24.13, sur le commit `0b216ef` de zod du 2 octobre 2026, avec un `tsconfig` limité aux sources de `packages/zod/src` (tests et bancs d'essai exclus, `noEmit`, `strict`). Valeurs internes rapportées par `--extendedDiagnostics`, médianes de dix passes alternées. La machine faisait tourner d'autres tâches pendant la mesure, d'où une dispersion notable entre passes : deux séries de dix passes ont donné 4,8 puis 3,7 secondes pour la version 6, mais le même rapport d'environ cinq avec la version 7. Le rapport est plus fiable que les temps absolus. La mémoire vient de la première série.



