Die Pipeline, Schritt für Schritt
- 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.
- 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.
- 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. - 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.
- 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.