Scriptc by Vercel: TypeScript-to-Native compiler, no JavaScript engine in binary

Vercel introduced Scriptc, a TypeScript-to-Native compiler that compiles standard TypeScript directly into compact native executables without embedding a JavaScript engine, achieving ~2ms startup times and minimal memory footprint.
Zero-runtime TypeScript. scriptc compiles ordinary TypeScript into small, fast native executables — no Node, no V8, no JavaScript engine in the binary.
$ cat fib.ts
function fib(n: number): number {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
console.log(fib(30));
$ scriptc run fib.ts
832040
$ scriptc build fib.ts && ls -la fib
-rwxr-xr-x 178K fib # a self-contained native binary, ~2ms startup
No changes to your code. No annotations, no dialect — the same TypeScript you run on Node, type-checked by the real TypeScript compiler and compiled to native. What compiles behaves byte-for-byte like Node.
$ npm install -g scriptc
Requires clang (preinstalled with Xcode Command Line Tools). macOS arm64 is the primary platform; Linux and Windows binaries build by cross-compilation, each verified by its own differential test lane.
Most TypeScript is far more static than the ecosystem assumes. scriptc decides, construct by construct, what can compile to native code — and tells you:
$ scriptc coverage app.ts
statements analyzed 4481
compile statically 4451 (99%)
blockers:
×2 functions with optional parameters as values SC1090
×1 Promise.reject SC2020
Three tiers, always explicit:
- Compiled statically — native code, no engine. The default, and the only mode unless you opt out.
- Runs dynamically (
--dynamic) — an embedded JavaScript engine (quickjs-ng, ~620KB) executes what can't be static: npm dependencies' shipped JS,any-typed code. Every value crossing back into static code is validated at runtime — a lying type throws a catchableTypeErrorinstead of corrupting memory. - Rejected — everything else fails with a specific error code, a code frame, and usually a rewrite hint. Nothing is ever silently miscompiled.
The static surface covers the language and the standard library real programs use:
- The language — classes with single inheritance and true dynamic dispatch, closures with JS capture semantics, generics (monomorphized), discriminated unions,
async/awaiton stackful fibers with JS-exact scheduling, exceptions withfinally, destructuring, spread, optional/default/rest parameters, getters/setters, iterators over strings/arrays/Maps/Sets, template literals, regular expressions. - The standard library — strings with UTF-16-exact semantics, arrays/Maps/Sets,
JSONwith runtime-validated casts,Math, typed arrays andBuffer,Errorhierarchies with typedcatch. - Node's API surface —
fs,path,process,child_process,os,crypto,url,zlib, timers,net,http,https,tls,dgram,dns,fs.watch,readline, and WHATWG web subset (fetch,Headers,AbortSignal).
Measured on Apple M-series against Node, Go, Rust, and Zig:
| Dimension | Scriptc | Context |
|---|---|---|
| Startup | ~2.4ms | Node: ~47ms; on par with Zig, ahead of Go/Rust |
| Binary size | 170–200KB static, ~3MB with --dynamic | Go: ~2MB; Node SEA: 60–100MB |
| Memory (RSS) | 1–4MB typical | Node: 67–116MB |
| Runtime | JS-faithful f64 semantics | Competitive with systems languages |
Architecture flow:
TS --> tsc (parse + typecheck) --> Typed IR --> C / LLVM --> clang --> Native Executable
Source: Hacker News
















