Um Compilador Nativo de TypeScript, Construído em Rust

O Perry compila o TypeScript que você já escreve para código de máquina — da mesma forma que um toolchain de Rust ou Go compila sua linguagem. Sem JavaScript transpilado, sem máquina virtual, sem runtime no sistema de destino.

Não é um transpilador. Não é um runtime.

A maior parte das ferramentas de TypeScript se divide em duas famílias. Transpiladores — tsc, SWC, esbuild — verificam e removem os tipos, depois emitem JavaScript para um motor executar depois. Runtimes — Node.js, Bun, Deno — são esses motores: eles analisam, interpretam e compilam o JavaScript via JIT toda vez que seu programa inicia.

Um compilador nativo é a terceira família, e para TypeScript ela tem estado praticamente vazia. O Perry trata as anotações de tipo não como documentação a ser removida, mas como a entrada que direciona a geração de código. O resultado de perry compile main.ts é um executável standalone contendo código de máquina — tipicamente 2–5 MB, iniciando em cerca de um milissegundo.

Como funciona

Do código-fonte TypeScript ao executável nativo em segundos

TypeScriptArquivos .ts
SWC
ParserAnálise rápida
HIR
TransformaçãoMonomorphization
LLVM
CodegenCódigo de máquina
ExecutávelBinário de 2-5 MB

Quer saber como o compilador funciona por dentro? Internos do compilador

Aprofundamento: TypeScript sobre LLVM — monomorfização, NaN-boxing, e por que o Perry deixou o Cranelift.

O pipeline, passo a passo

  1. Análise (SWC). Os arquivos-fonte são analisados com o SWC, o parser de TypeScript nativo em Rust, então até projetos grandes são analisados em milissegundos. A geração de código dos módulos, os passes de transformação e a varredura de símbolos rodam em paralelo entre os núcleos.
  2. Resolução de tipos. O compilador resolve os tipos declarados e infere o restante, dando a cada expressão um tipo concreto antes do início da geração de código.
  3. HIR tipado e monomorfização. A AST é rebaixada para um IR tipado de alto nível. Funções e classes genéricas são monomorfizadas — cada instanciação como Stack<number> é compilada separadamente com seus tipos concretos, então os generics não custam nada em tempo de execução. Onde os tipos são conhecidos, chamadas de método se tornam dispatch estático e campos de objeto se tornam acessos diretos, de deslocamento fixo.
  4. Codegen (LLVM). O HIR é rebaixado para LLVM IR e passa pelo pipeline de otimização do LLVM — inlining, otimizações de loop, vetorização — depois é emitido como código de máquina para o alvo.
  5. Link. A saída é um executável normal da plataforma: Mach-O no macOS, ELF no Linux, PE no Windows — além de alvos mobile, relógio, TV e WebAssembly.

O lado do LLVM nisso tudo — por que o LLVM foi escolhido em vez do Cranelift, como o NaN-boxing representa valores dinâmicos, o que o otimizador faz com IR tipado — tem seu próprio aprofundamento: TypeScript sobre LLVM. Detalhes de implementação como NaN-boxing, dispatch estático e abstrações de custo zero são cobertos em detalhes internos do compilador.

E quanto a código dinâmico e npm?

TypeScript continua sendo JavaScript por baixo, e um compilador nativo de TypeScript precisa ser honesto sobre isso. A conformidade do Perry com a suíte oficial test262 é medida e publicada — na v0.5.1146, a semântica de String está em 79% e a de Array em 72%, ambas subindo a cada release. Pacotes npm de TypeScript/JavaScript puro compilam nativamente via perry.compilePackages: axios, zod v4, express, fastify e hono compilam e rodam hoje. Código que precisa da semântica completa de um motor pode optar por um runtime V8 embutido opcional com --enable-js-runtime.

A história completa está em Pacotes npm reais e uma varredura de conformidade.

Como o Perry se relaciona com outros esforços de “TypeScript nativo”

O Perry não é o único projeto que olhou para as anotações de tipo do TypeScript e viu uma oportunidade de compilação — mas as abordagens diferem drasticamente. O AssemblyScript compila uma linguagem estrita parecida com TypeScript apenas para WebAssembly: ele é deliberadamente incompatível com JavaScript, e não produz executáveis de SO nem UI nativa. O Static Hermes da Meta compila ahead-of-time um subconjunto tipado de JavaScript dentro do motor Hermes, principalmente para o React Native — em meados de 2026 ele continua sendo um projeto de pesquisa que precisa ser compilado a partir do código-fonte, e o motor Hermes V1 que de fato chegou ao React Native não inclui os recursos estáticos (comparação completa).

A aposta do Perry é diferente em ambos os eixos: TypeScript padrão como linguagem de entrada, e executáveis comuns da plataforma — CLI, servidor e GUI — como saída, instaláveis hoje via Homebrew, APT, winget ou npm.

Um compilador, dez alvos

Como a geração de código passa pelo LLVM, um único código compila para macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly e Web/JS puro — incluindo compilação cruzada de binários Windows, macOS e iOS a partir de uma máquina Linux. Aplicações GUI usam perry/ui, uma API declarativa sobre widgets reais da plataforma (AppKit, UIKit, GTK4, Win32, Android via JNI) — sem nenhum webview envolvido.

Como isso se compara a outras abordagens: Perry vs Bun, Deno, Electron, Tauri, React Native e Static Hermes.

Experimente o compilador

Instale o Perry e compile seu primeiro binário nativo em menos de um minuto.