ternTS · written in Tern · experimental
TypeScript, exactly like tsc. 6× faster than swc.
ternTS turns TypeScript into the JavaScript tsc would write, including the legacy decorators and emitDecoratorMetadata that NestJS, TypeORM and Angular run on. Same output on 37,000 real files; a fraction of the time.
nest start --watch 676 msPlayground
Type TypeScript, get tsc’s JavaScript.
This is ternTS itself, compiled to WebAssembly and running in this page. Turn on Compare with tsc to run TypeScript 5.9’s transpileModule beside it and check the two outputs parse to the same program.
Your code
Run it on a whole project.
Pick a folder, drop one here, or load a public GitHub repository. ternTS transpiles every .ts and .tsx file (skipping node_modules, dist and .d.ts), then tsc does the same so you can compare. Nothing is uploaded: it all runs in your browser.
In the browser ternTS runs as single-threaded WebAssembly. The native ternts build uses every core and skips unchanged files, so it’s faster still. Options here are ternTS’ defaults (legacy decorators with metadata, ES2022+ output); ternts build reads them from your tsconfig.json.
Benchmarks
Faster than the Rust and Go rewrites.
Apple M4 Pro, Node 24, the latest release of each tool: swc 1.16.12, TypeScript 5.9.3, tsgo 7.0.2. node bench/run.mjs in the ternTS repository reproduces every number. Shorter bars are better.
Correct
tsc’s output, checked three ways.
1. The same program as tsc. Every file goes through ternTS and through TypeScript 5.9’s transpileModule with the same options, and both outputs are parsed and compared, ignoring only formatting and the numbering of temp names like _a. That’s the check the playground above runs.
2. Nest’s own test suite. All 3,631 of Nest’s unit tests pass with ternTS as the TypeScript transformer.
3. Real apps, same behavior. Nine NestJS sample apps built with tsc and with ternTS answer the same requests byte for byte, including the Swagger document and GraphQL schema that Nest builds from decorator metadata.
| Corpus | Files | Identical |
|---|---|---|
| NestJS repository | 1,959 | 1,959 |
| VS Code | 13,454 | 13,432* |
| Grafana + Excalidraw (4,948 .tsx) | 10,181 | 10,181 |
| Immich server | 668 | 668 |
| Twenty server | 11,057 | 11,057 |
* The 22 VS Code files that differ aren’t valid TypeScript on purpose (lint-error fixtures, a file cut off at 8 MB). tsc emits something for them anyway; ternTS reports the syntax error. Every corpus is identical in CommonJS, ES modules, with esModuleInterop + strictNullChecks, and with useDefineForClassFields; the .tsx files in all four JSX modes.
Experimental
Install
An early, experimental release: expect rough edges, and please tell us what breaks. The npm package carries a native binary for macOS and Linux (arm64 and x64) and WebAssembly for everything else, so you never install Tern.
npm i -D @ternlang/ternts@experimental
npx ternts build # the project in ./tsconfig.json: files, outDir, module, decorators, jsx…
npx ternts dev --warm # build, run, and restart on every save (replaces nest start --watch)Jest
// jest.config.js
transform: {
'^.+\\.(t|j|mj)sx?$': ['@ternlang/ternts/jest', { tsconfig: 'tsconfig.json' }],
}Vite and Vitest
// vite.config.ts
import ternts from '@ternlang/ternts/vite';
export default defineConfig({ plugins: [ternts()] });Node
# run TypeScript directly (Node 22.15+) node --import @ternlang/ternts/register src/main.ts
Not done yet
- Type checking, by design: keep
tsc --noEmit(or tsgo) for that, as swc users do. - Targets below ES2022. Output uses class fields and static blocks: Node 16.11+ and current browsers.
- TC39 standard decorators. Only the legacy kind (
experimentalDecorators), which NestJS, TypeORM and Angular use. - Windows has the WebAssembly build for Jest, Vite and Node, but not
ternts buildyet.
Written in Tern
About 10,000 lines of Tern.
ternTS is written in Tern, a compiled language built for AI agents to write, that compiles to native code faster than Rust and Go. There’s no AST: the parser walks tokens and copies your source through, editing only what TypeScript adds.
Meet Tern →