The pipeline, step by step
- Parse (SWC). Source files are parsed with SWC, the Rust-native TypeScript parser, so even large projects parse in milliseconds. Module codegen, transform passes, and symbol scanning run in parallel across cores.
- Type resolution. The compiler resolves declared types and infers the rest, giving every expression a concrete type before code generation begins.
- Typed HIR & monomorphization. The AST is lowered to a typed high-level IR. Generic functions and classes are monomorphized — each instantiation like
Stack<number> is compiled separately with its concrete types, so generics cost nothing at run time. Where types are known, method calls become static dispatch and object fields become direct, fixed-offset loads. - Codegen (LLVM). The HIR is lowered to LLVM IR and run through LLVM's optimization pipeline — inlining, loop optimizations, vectorization — then emitted as machine code for the target.
- Link. The output is a normal platform executable: Mach-O on macOS, ELF on Linux, PE on Windows — plus mobile, watch, TV, and WebAssembly targets.
The LLVM side of this — why LLVM was chosen over Cranelift, how NaN-boxing represents dynamic values, what the optimizer does with typed IR — has its own deep dive: TypeScript on LLVM. Implementation details like NaN-boxing, static dispatch, and zero-cost abstractions are covered in the compiler internals.
What about dynamic code and npm?
TypeScript is still JavaScript underneath, and a native TypeScript compiler has to be honest about that. Perry's conformance against the official test262 suite is measured and published — as of v0.5.1146, String semantics are at 79% and Array at 72%, both climbing release over release. Pure TypeScript/JavaScript npm packages compile natively via perry.compilePackages: axios, zod v4, express, fastify, and hono compile and run today. Code that needs full engine semantics can opt into an embedded V8 fallback with --enable-js-runtime.
The full story is in Real npm packages and a conformance sweep.
How Perry relates to other “native TypeScript” efforts
Perry isn't the only project that has looked at TypeScript's type annotations and seen a compilation opportunity — but the approaches differ sharply. AssemblyScript compiles a strict TypeScript-like language to WebAssembly only: it is deliberately not JavaScript-compatible, and it doesn't produce OS executables or native UI. Meta's Static Hermes ahead-of-time compiles a typed JavaScript subset inside the Hermes engine, primarily for React Native — as of mid-2026 it remains a research project that must be built from source, and the Hermes V1 engine that actually shipped in React Native does not include the static features (full comparison).
Perry's bet is different on both axes: standard TypeScript as the input language, and ordinary platform executables — CLI, server, and GUI — as the output, installable today via Homebrew, APT, winget, or npm.
One compiler, ten targets
Because code generation goes through LLVM, one codebase compiles to macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly, and plain Web/JS — including cross-compiling Windows, macOS, and iOS binaries from a Linux machine. GUI apps use perry/ui, a declarative API over real platform widgets (AppKit, UIKit, GTK4, Win32, Android via JNI) — no webview involved.
How that stacks up against other approaches: Perry vs Bun, Deno, Electron, Tauri, React Native, and Static Hermes.