Un compilador nativo de TypeScript, construido en Rust

Perry compila el TypeScript que ya escribes a código máquina — de la misma forma en que un toolchain de Rust o Go compila su lenguaje. Sin JavaScript transpilado, sin máquina virtual, sin runtime en el sistema de destino.

No es un transpilador. No es un runtime.

La mayoría de las herramientas de TypeScript caen en dos familias. Los transpiladores — tsc, SWC, esbuild — verifican y eliminan los tipos, y luego emiten JavaScript para que un motor lo ejecute después. Los runtimes — Node.js, Bun, Deno — son esos motores: parsean, interpretan y compilan con JIT el JavaScript cada vez que arranca tu programa.

Un compilador nativo es la tercera familia, y para TypeScript ha estado prácticamente vacía. Perry trata las anotaciones de tipos no como documentación para eliminar, sino como la entrada que impulsa la generación de código. El resultado de perry compile main.ts es un ejecutable independiente que contiene código máquina — típicamente de 2–5 MB, arrancando en aproximadamente un milisegundo.

Cómo funciona

De código fuente TypeScript a ejecutable nativo en segundos

TypeScriptArchivos .ts
SWC
ParserAnálisis rápido
HIR
TransformaciónMonomorphization
LLVM
CodegenCódigo máquina
EjecutableBinario de 2-5 MB

¿Quieres saber cómo funciona el compilador internamente? Internos del compilador

Análisis a fondo: TypeScript sobre LLVM — monomorfización, NaN-boxing y por qué Perry abandonó Cranelift.

La pipeline, paso a paso

  1. Parseo (SWC). Los archivos fuente se parsean con SWC, el parser de TypeScript nativo en Rust, así que incluso los proyectos grandes se parsean en milisegundos. El codegen de módulos, los transform passes y el escaneo de símbolos se ejecutan en paralelo entre núcleos.
  2. Resolución de tipos. El compilador resuelve los tipos declarados e infiere el resto, dando a cada expresión un tipo concreto antes de que comience la generación de código.
  3. HIR tipado y monomorfización. El AST se reduce a un IR de alto nivel tipado (HIR). Las funciones y clases genéricas se monomorfizan — cada instanciación como Stack<number> se compila por separado con sus tipos concretos, así que los genéricos no cuestan nada en runtime. Donde los tipos son conocidos, las llamadas a métodos se convierten en static dispatch y los campos de los objetos se convierten en cargas directas de desplazamiento fijo.
  4. Codegen (LLVM). El HIR se reduce a LLVM IR y se pasa por la pipeline de optimización de LLVM — inlining, optimizaciones de bucles, vectorización — y luego se emite como código máquina para la plataforma de destino.
  5. Enlazado. La salida es un ejecutable normal de la plataforma: Mach-O en macOS, ELF en Linux, PE en Windows — además de plataformas móviles, de reloj, de TV y WebAssembly.

El lado de LLVM en todo esto — por qué se eligió LLVM sobre Cranelift, cómo NaN-boxing representa los valores dinámicos, qué hace el optimizador con el IR tipado — tiene su propio análisis a fondo: TypeScript sobre LLVM. Los detalles de implementación como NaN-boxing, static dispatch y las abstracciones de coste cero se cubren en los internos del compilador.

¿Qué pasa con el código dinámico y npm?

TypeScript sigue siendo JavaScript por debajo, y un compilador nativo de TypeScript tiene que ser honesto al respecto. La conformidad de Perry frente a la suite oficial test262 se mide y se publica — a fecha de v0.5.1146, la semántica de String está en 79% y la de Array en 72%, ambas subiendo con cada release. Los paquetes npm de TypeScript/JavaScript puro compilan de forma nativa mediante perry.compilePackages: axios, zod v4, express, fastify y hono compilan y se ejecutan hoy. El código que necesita la semántica completa de un motor puede optar por un fallback embebido con V8 mediante --enable-js-runtime.

La historia completa está en Paquetes npm reales y un barrido de conformidad.

Cómo se relaciona Perry con otros esfuerzos de «TypeScript nativo»

Perry no es el único proyecto que ha mirado las anotaciones de tipos de TypeScript y ha visto una oportunidad de compilación — pero los enfoques difieren radicalmente. AssemblyScript compila un lenguaje estricto parecido a TypeScript únicamente a WebAssembly: deliberadamente no es compatible con JavaScript, y no produce ejecutables de sistema operativo ni UI nativa. Static Hermes, de Meta, compila de forma anticipada un subconjunto tipado de JavaScript dentro del motor Hermes, principalmente para React Native — a mediados de 2026 sigue siendo un proyecto de investigación que debe compilarse desde el código fuente, y el motor Hermes V1 que realmente se distribuyó en React Native no incluye las funciones estáticas (comparación completa).

La apuesta de Perry es distinta en ambos ejes: TypeScript estándar como lenguaje de entrada, y ejecutables de plataforma comunes — CLI, servidor y GUI — como salida, instalable hoy vía Homebrew, APT, winget o npm.

Un compilador, diez plataformas

Como la generación de código pasa por LLVM, un único código fuente compila a macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly y Web/JS puro — incluyendo la compilación cruzada de binarios de Windows, macOS e iOS desde una máquina Linux. Las apps GUI usan perry/ui, una API declarativa sobre widgets reales de la plataforma (AppKit, UIKit, GTK4, Win32, Android vía JNI) — sin ningún webview involucrado.

Cómo se compara eso frente a otros enfoques: Perry frente a Bun, Deno, Electron, Tauri, React Native y Static Hermes.

Prueba el compilador

Instala Perry y compila tu primer binario nativo en menos de un minuto.