Native stripping covers most projects. When it does not — a shared module that uses enums, a tsconfig.json full of paths aliases, or .tsx files shared with a front end — the Node documentation names one replacement: tsx 12,162 (github.com/privatenumber/tsx (https://github.com/privatenumber/tsx 12,162 ), MIT, 12.1k stars). Its only runtime dependency is esbuild 126 , which compiles rather than strips. Install with npm 2,036 i -D tsx, then run npx tsx src/server.ts or node --import=tsx src/server.ts.
That second form matters: --import=tsx registers tsx as a module customization hook (Module Customization Hooks) inside a normal node process, so every other Node flag — --inspect, --env-file, --max-old-space-size — keeps working as it does for JavaScript.
tsx watch restarts on every save and knows the import graph, so editing a module restarts the entry point that depends on it:
$ npx tsx watch --clear-screen=false src/tick.ts first 11:54:05 7:54:08 PM [tsx] change in ./src\tick.ts Rerunning... second 11:54:08
Node's own --watch (Watch Mode and Scripts) does the same for stripped files and costs no dependency, so reach for tsx watch only when you already need tsx for its compilation.
| node app.ts | tsx app.ts | ts-node 13,120 | |
|---|---|---|---|
| Enums, decorators, .tsx | No | Yes | Yes |
| tsconfig.json paths | Ignored | Honored | Honored |
| Type checking | No | No | Optional, slow |
| Direct dependencies | 0 | 1 (esbuild) | 13 |
ts-node is the tool every older tutorial reaches for. It still works, but 10.9.2 was published in December 2023 and nothing has shipped since, it type-checks by default (which is why it feels slow), and it pulls in thirteen direct dependencies. And tsx does not check types either, so a project that runs perfectly under tsx can still be full of type errors.