devdot
← All postsEngineering ·

Node Runs TypeScript Natively Now. Keep Your Build Step Anyway.

Node.js now strips TypeScript types and runs .ts files with no compile step. It is a real ergonomics win for scripts and tooling, but it does not type-check your code, so your build pipeline still has a job.

Run node app.ts and it just works now. No ts-node, no tsx, no compile step first. As of the 22.18 release, type stripping is on by default, which means Node can execute a TypeScript file directly. For anyone who has spent years wiring up a toolchain just to run a 40-line script, this feels overdue.

It is a genuinely nice change. It is also easy to misread. So here is what you actually get, and what you very much do not.

What "native TypeScript" really means

Node is not type-checking your code. It strips the types out and runs the JavaScript that is left. Your annotations, your interfaces, your type-only imports all get replaced with whitespace so the line numbers still match, and then the engine runs plain JS. That is the entire trick. It is fast precisely because it does less.

So the thing TypeScript is famous for, catching your mistakes before they reach production, is not happening at runtime. Node will happily run code that tsc would reject outright. A type error is not a syntax error to the runtime. It is invisible.

That is the part worth sitting with. "Node runs TypeScript" and "Node checks your TypeScript" are two very different sentences, and only the first one is true.

Where this is an actual win

Scripts and one-off tooling. This is where it shines. Migration scripts, seed files, local CLIs, glue code, the throwaway .ts you write to poke at an API. All the places where you wanted types for editor help but a full build pipeline was pure overhead. Now you skip the ceremony and run the file.

It also trims a dependency. Removing ts-node or tsx from a repo is a small thing, but small things add up across a team and a CI config.

For quick internal servers and prototypes, it lowers the barrier to starting in TypeScript at all. That is a good default to encourage.

Where you still need the build step

Two reasons, and neither is going away.

First, type-checking. If the runtime does not verify types, something else has to. That job belongs in tsc --noEmit running in CI and in your editor. Type stripping is a runtime convenience, not a replacement for the compiler as a gate. Ship a repo without that gate and you have essentially opted back into untyped JavaScript with extra syntax.

Second, syntax coverage. Stripping handles annotations cleanly, but TypeScript features that generate real JavaScript, like enums, namespaces, parameter properties, and some decorator setups, are not plain strip-and-go. They need --experimental-transform-types or a real compiler. Lean on those features and the "it just works" story gets qualified fast.

And for anything user-facing, you still want a bundler doing tree-shaking, minification, and target downleveling. Node running your source is not the same as shipping an optimised artifact.

The take

Use native stripping for the small stuff. Scripts, tooling, local servers, prototypes. Let it kill the boilerplate it is good at killing.

Keep tsc as the gate for everything real. Type-check in CI, type-check in your editor, and keep your bundler for production builds. Treat the new runtime feature as a faster on-ramp, not a reason to delete your pipeline. The teams that get burned here will be the ones who read "native TypeScript" and quietly stopped type-checking.

We are here to help founders and teams design and build digital products that are built to scale with you, not slow you down. If you are looking to build something, get in contact with us today!

NEXT POST →Your AI Vendor Might Be 5% Government-Owned. Price In the Governance Risk.