Um dev, um Claude e 15.197 testes: como o TypeScript ganhou um compilador em Rust
Quando a Microsoft reescreveu o compilador do TypeScript em Go e lançou a versão 7.0 em julho de 2026, o mundo JavaScript respirou aliviado. Builds 10x mais rápidos. Type-checking do VS Code caindo de 125 segundos para 10. Parecia que o problema de performance do TypeScript tinha sido resolvido de vez.
Até que Max Schwenk, da Owner.com, olhou para o monorepo da empresa (37.000 arquivos TypeScript) e pensou: “dá pra ir mais rápido”. Ele abriu o Claude Opus 5.5, apontou para o código Go do compilador e pediu: “porta isso para Rust”. O resultado é o tsrs, um compilador TypeScript em Rust que é 8x mais rápido que a versão Go e usa 70% menos memória.
E não, isso não é um projeto de garagem. A Cloudflare, a VoidZero (empresa do Evan You, criador do Vue.js) e o próprio time do TypeScript na Microsoft estão envolvidos. O projeto já faz parte do Oxc, o toolchain JavaScript em Rust que está engolindo o ecossistema.
A linha do tempo que explica tudo
Pra entender o tsrs, precisa entender o que aconteceu antes:
| Ano | Evento |
|---|---|
| 2012 | TypeScript nasce, compilador escrito em… TypeScript |
| 2024 | Microsoft anuncia que vai reescrever o compilador em Go |
| Jul 2026 | TypeScript 7.0 sai com compilador Go: 10x mais rápido |
| Set 2026 | Max Schwenk começa a portar o Go para Rust usando IA |
| Out 2026 | tsrs é anunciado publicamente com benchmarks impressionantes |
A versão Go já era uma revolução. O VS Code, que levava 77.8 segundos para compilar no TypeScript 6, passou a compilar em 7.5 segundos. O TypeORM saiu de 17.5 para 1.3 segundos. Mas o Go tem uma limitação que a Cloudflare não podia ignorar: não compila bem para WebAssembly.
Por que Rust e não Go?
A resposta curta: WebAssembly.
A Cloudflare roda tudo em Workers, que são basicamente ambientes WebAssembly com limites apertados de memória. O Go, por carregar um garbage collector junto, gera binários WASM pesados e imprevisíveis em consumo de memória. O Rust, por outro lado, compila para WASM sem nenhum runtime extra.
Mas tem mais. A versão Rust trouxe otimizações que o Go simplesmente não consegue igualar:
Compressão de ponteiros: o tsrs reduziu o tamanho de cada ponteiro de 8 para 4 bytes usando endereçamento por offset dentro de blocos de memória reservados. Só isso cortou 14 a 15% do consumo de memória.
Resolução lazy de membros: em vez de construir todos os membros de tipos genéricos antecipadamente, o compilador só materializa propriedades quando alguém pede. Resultado: 23% menos memória.
Layouts menores de objetos: reorganização das estruturas de dados cortou mais 21% de memória.
Liberação de arquivos folha: em modo noEmit, árvores sintáticas de arquivos não importados são descartadas, economizando 13 a 16% de memória no pico.
Somando tudo, o resultado no monorepo da Owner (37.000 arquivos) fica assim:
| Métrica | tsgo 7.0.2 (4 checkers) | tsrs 0.14.0 (4 checkers) |
|---|---|---|
| Tempo | 61.4 segundos | 8.75 segundos |
| Memória pico | 36.0 GiB | 6.1 GiB |
| Melhoria | base | 7.0x mais rápido, 5.9x menos memória |
Com 16 checkers, o tsrs chegou a 4.24 segundos. Um monorepo de 37 mil arquivos TypeScript checado em menos de 5 segundos.
Como uma IA portou um compilador inteiro
Essa parte é quase inacreditável. Max Schwenk não sentou e reescreveu linha por linha. Ele usou o Claude Opus 5.5 com uma abordagem metodológica:
- Cada pacote Go virou um crate Rust separado
- Agentes de IA trabalharam em paralelo nos diferentes crates
- A regra era clara: “mesmos algoritmos, mesma estrutura de funções, mesma ordem de avaliação, mesmos diagnósticos”
- Os 15.197 testes de conformidade do TypeScript serviram como especificação
Na primeira execução, o compilador portado por IA atingiu 78% de paridade byte-a-byte nos erros gerados. Depois de implementar o type printer, chegou a 99.97%.
Eu sei o que você está pensando: “mas IA gerando compilador? Isso funciona de verdade?” Funciona. Mas não porque a IA entende teoria de compiladores. Funciona porque a porta foi mecânica: mesma lógica, mesma estrutura, só mudando a linguagem. É o tipo de tarefa onde LLMs brilham: tradução fiel de código com testes automatizados para validar cada passo.
O projeto rodou 200.000 mutações no parser todas as noites comparando com a referência. Usou Miri para verificação de segurança de memória. E rodou em três modos de execução diferentes (single-thread, scheduling padrão e randomizado) para garantir que a saída fosse sempre idêntica.
Dois bugs sérios foram pegos: um atalho que passava toda a suíte de testes mas engolia erros silenciosamente, e um use-after-free que só aparecia em builds otimizados. Sem os testes automatizados, nenhum dos dois teria sido detectado.
O ecossistema Oxc: por que isso importa
O tsrs não é um projeto isolado. Ele está se juntando ao Oxc (Oxidation Compiler), o toolchain JavaScript em Rust liderado por Boshen Chen na Cloudflare e pela VoidZero do Evan You.
O Oxc já tem:
- Parser: o mais rápido do mercado para JavaScript/TypeScript
- Oxlint: linter 100x mais rápido que o ESLint
- Formatter: 30x mais rápido que o Prettier
- Transformer: substitui o Babel
- Minifier: alternativa ao Terser/esbuild
Todos compartilham o mesmo AST, então o código nunca é parseado duas vezes. O tsrs adiciona type-checking a esse pipeline, e o resultado é um toolchain completo em Rust que faz tudo: parsear, checar tipos, lintar, formatar, transformar e minificar.
O Vite 8 já usa o Oxc para transforms e minificação. O Rolldown 1.0 (bundler Rust que substitui o Rollup) está estável desde maio de 2026. O ecossistema está convergindo para uma realidade onde toda a toolchain JavaScript roda em Rust, com performance que seria impensável há dois anos.
Work stealing e paralelismo real
Além das otimizações de memória, o tsrs implementou melhorias no paralelismo que o compilador Go não tem.
O modelo original do TypeScript 7.0 distribui arquivos entre checkers numa fase de binding. Cada checker processa seus arquivos independentemente e mantém seu próprio grafo de tipos. O problema: se um checker termina cedo enquanto outro está atolado com arquivos pesados, ele fica ocioso esperando.
O tsrs resolveu isso com work stealing. Quando um checker termina seus arquivos, ele rouba arquivos não iniciados da fila de checkers ocupados. Na prática, isso reduziu o wall time em 13.8 a 17%.
Outra otimização foi o agrupamento por imports: arquivos que importam as mesmas bibliotecas são agrupados no mesmo checker, reduzindo a duplicação de instanciação de tipos de bibliotecas entre checkers. O time testou compartilhar tipos entre checkers, mas descobriu que isso causava inconsistências na saída sem ganho real de performance. A decisão foi manter checkers isolados com determinismo garantido via CI gate que testa três modos de execução.
Esse nível de engenharia de paralelismo é viável em Rust porque a linguagem garante segurança de concorrência em tempo de compilação. O borrow checker do Rust impede data races por design, algo que em Go depende inteiramente da disciplina do programador.
Como testar agora
O tsrs já está disponível no npm:
npm install --save-dev tsrs
Para rodar contra seu projeto existente:
npx tsrs -p . --noEmit
Ele lê seu tsconfig.json e faz type-checking normalmente. A experiência é drop-in: mesmos erros, mesmas mensagens, mesma saída. Se o seu código passa no tsc, vai passar no tsrs.
Se você quer testar no browser via WebAssembly:
npm install @tsrs/wasm
A versão WASM ainda é single-threaded e tem limite de 4 GiB por instância, mas já funciona para projetos menores. Watch mode e language server estão no roadmap.
Um exemplo prático de como o tsrs se integra num pipeline de CI existente:
# .github/workflows/typecheck.yml
name: Type Check
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx tsrs -p . --noEmit
Troque tsc por tsrs e pronto. Se algo quebrar, o tsrs gera exatamente os mesmos erros, nos mesmos arquivos, nas mesmas linhas.
Em benchmarks com 17 projetos open source, o tsrs usou em média 3x menos memória e rodou 2.5 a 5x mais rápido que o TypeScript nightly.
“Não estamos forkando o TypeScript”
A Cloudflare fez questão de deixar isso bem claro. O tsrs segue o TypeScript upstream à risca. Cada decisão de design do time da Microsoft é respeitada. Bugs encontrados são reportados de volta, e melhorias de performance já foram incorporadas ao TypeScript 7.1, que ficou 2.5x mais rápido que o 7.0 em parte graças ao trabalho do tsrs.
O modelo de manutenção é parecido com o Vinext (fork do Next.js da Cloudflare): agentes automatizados rastreiam mudanças upstream, rodam testes de compatibilidade toda noite e identificam patches relevantes para portar.
Isso é importante porque forks morrem. O CoffeeScript morreu. O Flow morreu. Projetos que divergem do ecossistema principal acabam isolados. O tsrs evita isso por design: é uma porta fiel, não uma reimaginação.
O impacto no dia a dia
Na Owner.com, o antes e depois é brutal:
- Type-checking: de 80 para 7 segundos
- Linting com type-aware: de 169.4 para 37.3 segundos (4.5x)
- Múltiplos agentes de IA rodando em paralelo no monorepo se tornaram viáveis localmente
- Economia projetada: centenas de milhares de dólares por ano em infraestrutura
Para a Cloudflare, o ganho é ainda mais estratégico. Com o compilador rodando em WASM dentro de Workers, eles podem oferecer type-checking como serviço na edge. Imagine rodar tsc em um Worker com 128 MB de memória, sem provisionar servidor. Isso não era possível com Go.
Para devs comuns, a pergunta prática é: vale a pena trocar agora? Se você tem um projeto pequeno (menos de 1.000 arquivos), provavelmente não vai sentir diferença. O TypeScript 7.0 em Go já é rápido o suficiente. Mas se seu monorepo tem milhares de arquivos e o CI fica travado esperando type-checking, o tsrs pode cortar minutos do seu pipeline.
A guerra dos compiladores TypeScript
Agora existem três compiladores TypeScript competindo:
| Compilador | Linguagem | Mantenedor | Status |
|---|---|---|---|
| tsc (TypeScript 7.x) | Go | Microsoft | Estável, produção |
| tsrs | Rust | Cloudflare/VoidZero/Owner | Experimental |
| Bun checker | Zig (nativo) | Oven | Em desenvolvimento |
A Microsoft lidera com a versão oficial em Go. O tsrs aposta que Rust + WASM é o futuro das ferramentas JavaScript. E o Bun, como sempre, faz tudo do jeito dele com o checker nativo em Zig.
No fim, quem ganha é o desenvolvedor. Três anos atrás, esperar 2 minutos para o TypeScript checar um projeto grande era normal. Hoje, qualquer uma dessas opções faz isso em segundos. A briga agora é por milissegundos.
Theo Browne (do canal t3.gg) também estava trabalhando em um port independente de TypeScript para Rust, o que mostra que a demanda por isso era real. A comunidade queria Rust, e agora tem.
O que vem pela frente
O roadmap do tsrs inclui:
- Language Server Protocol (LSP): autocomplete e go-to-definition em Rust, integrado com editores
- Watch mode: recompilação incremental quando arquivos mudam
- Conformidade total com TypeScript 7.1: a meta é 100% de paridade
- Integração profunda com Oxc: type-checking inline durante linting e bundling
A fusão com o tsc-rs (outro port em Rust) já está em andamento, e o repositório foi transferido para a liderança do projeto Oxc (Boshen Chen, Cloudflare, VoidZero).
Se o Oxc conseguir entregar um toolchain completo em Rust com parser + checker + linter + formatter + bundler + minifier, todos compartilhando o mesmo AST, a velocidade final vai ser algo que ninguém imaginou ser possível no ecossistema JavaScript.
E tudo começou com um dev que olhou para 37.000 arquivos TypeScript e decidiu que “rápido o suficiente” não era suficiente.
O elefante na sala: e se a Microsoft não gostar?
A pergunta que ninguém faz em voz alta: o que a Microsoft pensa disso?
Até agora, a relação parece cooperativa. O time do TypeScript participou do processo, e melhorias do tsrs já foram incorporadas ao upstream. Mas a dinâmica pode mudar. A Microsoft investiu anos e milhões de dólares na reescrita em Go. Se o tsrs se tornar o padrão de fato, a versão oficial vira uma peça de museu.
Por outro lado, a Microsoft não é boba. Se o Rust se provar melhor, eles podem simplesmente adotar o tsrs como backend oficial. Não seria a primeira vez que a Microsoft abraça um projeto da comunidade (vide o VS Code, que nasceu do Atom da GitHub, e o próprio TypeScript, que surgiu para cobrir buracos do JavaScript).
O cenário mais provável? Coexistência. O compilador Go oficial para quem quer estabilidade máxima. O tsrs para quem precisa de WASM ou está espremendo cada milissegundo de CI. E o Bun fazendo Bun things no canto dele.
Já dá pra instalar o tsrs e apontar pro seu tsconfig.json hoje. A pergunta não é se o ecossistema TypeScript vai migrar pra Rust, é quando.













