Ein nativer TypeScript-Compiler, gebaut in Rust

Perry kompiliert das TypeScript, das du bereits schreibst, zu Maschinencode — so wie eine Rust- oder Go-Toolchain ihre eigene Sprache kompiliert. Kein transpiliertes JavaScript, keine virtuelle Maschine, keine Laufzeitumgebung auf dem Zielsystem.

Kein Transpiler. Keine Laufzeitumgebung.

Die meisten TypeScript-Tools lassen sich in zwei Familien einteilen. Transpiler — tsc, SWC, esbuild — prüfen die Typen und entfernen sie, um dann JavaScript für eine Engine auszugeben, die es später ausführt. Laufzeitumgebungen — Node.js, Bun, Deno — sind diese Engines: Sie parsen, interpretieren und JIT-kompilieren das JavaScript bei jedem Start deines Programms.

Ein nativer Compiler ist die dritte Familie, und für TypeScript war sie bisher weitgehend leer. Perry behandelt Typannotationen nicht als Dokumentation, die entfernt wird, sondern als die Eingabe, die die Codegenerierung antreibt. Das Ergebnis von perry compile main.ts ist ein eigenständiges Executable mit Maschinencode — typischerweise 2–5 MB, startet in etwa einer Millisekunde.

So funktioniert's

Von TypeScript-Quellcode zum nativen Binary in Sekunden

TypeScript.ts-Dateien
SWC
ParserSchnelles Parsen
HIR
TransformationMonomorphization
LLVM
CodegenMaschinencode
Ausführbare Datei2–5 MB Binary

Willst du wissen, wie der Compiler unter der Haube funktioniert? Compiler-Interna

Tiefer eintauchen: TypeScript auf LLVM — Monomorphisierung, NaN-Boxing und warum Perry Cranelift verlassen hat.

Die Pipeline, Schritt für Schritt

  1. Parsen (SWC). Quelldateien werden mit SWC geparst, dem nativen TypeScript-Parser in Rust, sodass selbst große Projekte in Millisekunden geparst werden. Modul-Codegen, Transformations-Durchläufe und Symbol-Scanning laufen parallel über alle Kerne.
  2. Typauflösung. Der Compiler löst deklarierte Typen auf und leitet den Rest ab, sodass jeder Ausdruck vor Beginn der Codegenerierung einen konkreten Typ hat.
  3. Typisierte HIR & Monomorphisierung. Der AST wird zu einer typisierten High-Level-IR abgesenkt. Generische Funktionen und Klassen werden monomorphisiert — jede Instanziierung wie Stack<number> wird separat mit ihren konkreten Typen kompiliert, sodass Generics zur Laufzeit nichts kosten. Wo Typen bekannt sind, werden Methodenaufrufe zu statischem Dispatch und Objektfelder zu direkten Ladevorgängen mit festem Offset.
  4. Codegen (LLVM). Die HIR wird zu LLVM-IR abgesenkt und durch die Optimierungs-Pipeline von LLVM geführt — Inlining, Schleifenoptimierungen, Vektorisierung — und dann als Maschinencode für das Ziel ausgegeben.
  5. Linken. Die Ausgabe ist ein normales Plattform-Executable: Mach-O auf macOS, ELF auf Linux, PE auf Windows — plus Ziele für Mobile, Watch, TV und WebAssembly.

Die LLVM-Seite davon — warum LLVM gegenüber Cranelift gewählt wurde, wie NaN-Boxing dynamische Werte darstellt, was der Optimierer mit typisierter IR macht — hat einen eigenen Deep Dive: TypeScript auf LLVM. Implementierungsdetails wie NaN-Boxing, statischer Dispatch und kostenlose Abstraktionen werden in den Compiler-Interna behandelt.

Was ist mit dynamischem Code und npm?

TypeScript ist darunter immer noch JavaScript, und ein nativer TypeScript-Compiler muss darüber ehrlich sein. Perrys Konformität gegenüber der offiziellen test262-Suite wird gemessen und veröffentlicht — Stand v0.5.1146 liegt die String-Semantik bei 79 % und Array bei 72 %, beide steigen von Release zu Release. Reine TypeScript-/JavaScript-npm-Pakete kompilieren nativ über perry.compilePackages: axios, zod v4, express, fastify und hono kompilieren und laufen bereits heute. Code, der volle Engine-Semantik benötigt, kann sich für einen eingebetteten V8-Fallback mit --enable-js-runtime entscheiden.

Die vollständige Geschichte steht in Real npm packages and a conformance sweep.

Wie Perry zu anderen “nativen TypeScript”-Ansätzen steht

Perry ist nicht das einzige Projekt, das in TypeScripts Typannotationen eine Kompilierungschance gesehen hat — aber die Ansätze unterscheiden sich stark. AssemblyScript kompiliert eine strikte, TypeScript-ähnliche Sprache ausschließlich zu WebAssembly: Es ist bewusst nicht JavaScript-kompatibel und erzeugt weder OS-Executables noch native UI. Metas Static Hermes kompiliert ahead-of-time einen typisierten JavaScript-Subset innerhalb der Hermes-Engine, primär für React Native — Stand Mitte 2026 bleibt es ein Forschungsprojekt, das aus dem Quellcode gebaut werden muss, und die Hermes-V1-Engine, die tatsächlich in React Native ausgeliefert wurde, enthält die statischen Features nicht (vollständiger Vergleich).

Perrys Wette ist auf beiden Achsen anders: Standard-TypeScript als Eingabesprache und gewöhnliche Plattform-Executables — CLI, Server und GUI — als Ausgabe, heute installierbar über Homebrew, APT, winget oder npm.

Ein Compiler, zehn Ziele

Weil die Codegenerierung über LLVM läuft, kompiliert eine Codebasis zu macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly und einfachem Web/JS — einschließlich Cross-Compilation von Windows-, macOS- und iOS-Binaries von einer Linux-Maschine aus. GUI-Apps nutzen perry/ui, eine deklarative API über echte Plattform-Widgets (AppKit, UIKit, GTK4, Win32, Android über JNI) — ohne jede Webview.

Wie das im Vergleich zu anderen Ansätzen abschneidet: Perry vs Bun, Deno, Electron, Tauri, React Native und Static Hermes.

Probiere den Compiler aus

Installiere Perry und kompiliere deine erste native Binary in unter einer Minute.