Pipeline, từng bước một
- Parse (SWC). Tệp nguồn được parse bằng SWC, trình phân tích cú pháp TypeScript viết bằng Rust, nên ngay cả dự án lớn cũng được parse trong vài mili giây. Sinh mã module, các transform pass và quét symbol chạy song song trên nhiều lõi.
- Giải quyết kiểu. Trình biên dịch giải quyết các kiểu đã khai báo và suy luận phần còn lại, gán cho mỗi biểu thức một kiểu cụ thể trước khi việc sinh mã bắt đầu.
- HIR có kiểu & monomorphization. AST được hạ cấp thành một IR bậc cao có kiểu (HIR). Hàm và lớp generic được monomorphize — mỗi lần khởi tạo như
Stack<number> được biên dịch riêng với kiểu cụ thể của nó, nên generic không tốn chi phí gì lúc runtime. Khi kiểu đã biết, lệnh gọi phương thức trở thành static dispatch và trường đối tượng trở thành phép đọc trực tiếp với offset cố định. - Sinh mã (LLVM). HIR được hạ cấp thành LLVM IR và chạy qua pipeline tối ưu hóa của LLVM — inlining, tối ưu hóa vòng lặp, vector hóa — rồi được xuất thành mã máy cho mục tiêu.
- Liên kết. Đầu ra là một tệp thực thi nền tảng bình thường: Mach-O trên macOS, ELF trên Linux, PE trên Windows — cộng với các mục tiêu di động, watch, TV và WebAssembly.
Phần liên quan đến LLVM — tại sao LLVM được chọn thay vì Cranelift, NaN-boxing biểu diễn giá trị động ra sao, trình tối ưu hóa làm gì với IR có kiểu — có bài tìm hiểu chuyên sâu riêng: TypeScript trên LLVM. Chi tiết triển khai như NaN-boxing, static dispatch và zero-cost abstraction được trình bày trong cấu trúc bên trong trình biên dịch.
Còn mã động và npm thì sao?
TypeScript về bản chất vẫn là JavaScript, và một trình biên dịch TypeScript gốc phải thẳng thắn thừa nhận điều đó. Độ tuân thủ của Perry với bộ test262 chính thức được đo lường và công bố — tính đến v0.5.1146, ngữ nghĩa String đạt 79% và Array đạt 72%, cả hai đều tăng dần qua từng bản phát hành. Các gói npm TypeScript/JavaScript thuần biên dịch gốc qua perry.compilePackages: axios, zod v4, express, fastify và hono đã có thể biên dịch và chạy ngay hôm nay. Mã cần đầy đủ ngữ nghĩa engine có thể dùng tùy chọn V8 nhúng dự phòng với --enable-js-runtime.
Câu chuyện đầy đủ nằm trong Các package npm thực tế và một lượt quét conformance.
Perry liên hệ thế nào với các nỗ lực “TypeScript gốc” khác
Perry không phải là dự án duy nhất nhìn vào chú thích kiểu của TypeScript và thấy một cơ hội biên dịch — nhưng cách tiếp cận khác nhau rất nhiều. AssemblyScript chỉ biên dịch một ngôn ngữ giống TypeScript nghiêm ngặt sang WebAssembly: nó cố tình không tương thích JavaScript, và không tạo ra tệp thực thi hệ điều hành hay UI gốc. Static Hermes của Meta biên dịch ahead-of-time một tập con JavaScript có kiểu bên trong engine Hermes, chủ yếu cho React Native — tính đến giữa năm 2026 nó vẫn là một dự án nghiên cứu phải được build từ mã nguồn, và engine Hermes V1 thực sự được đưa vào React Native không bao gồm các tính năng biên dịch tĩnh (so sánh đầy đủ).
Canh bạc của Perry khác biệt trên cả hai trục: TypeScript chuẩn làm ngôn ngữ đầu vào, và các tệp thực thi nền tảng thông thường — CLI, server và GUI — làm đầu ra, có thể cài đặt ngay hôm nay qua Homebrew, APT, winget hoặc npm.
Một trình biên dịch, mười mục tiêu
Vì việc sinh mã đi qua LLVM, một mã nguồn duy nhất biên dịch được sang macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly và Web/JS thuần — bao gồm cả biên dịch chéo binary Windows, macOS và iOS từ một máy Linux. Ứng dụng GUI sử dụng perry/ui, một API khai báo trên các widget nền tảng thực sự (AppKit, UIKit, GTK4, Win32, Android qua JNI) — không có webview nào liên quan.
So sánh với các cách tiếp cận khác thế nào: Perry vs Bun, Deno, Electron, Tauri, React Native và Static Hermes.