Node.js Native TypeScript type stripping with Node 24 and amaro
product-development12 min readintermediate

Node.js Native TypeScript in 2026: Type Stripping Without a Build Step

Vivek Singh
Founder & CEO at Witarist · May 27, 2026

For more than a decade, every Node.js team has paid the same tax: a build step. TypeScript code had to be compiled by tsc, transformed by ts-node, or bundled by esbuild before Node could run it. That changed quietly in 2024 — and in 2026 it's the new default. Node 24 ships with native type stripping enabled out of the box, so `node app.ts` Just Works. No tsconfig.json required. No build artefacts. No watch mode.

This guide is a production playbook for native TypeScript on Node.js: what type stripping actually does (and what it does not), how it compares to ts-node, tsx, Bun, and Deno, the syntax restrictions you must understand before you commit to it, and the CI patterns that keep your codebase safe when the runtime no longer type-checks for you. By the end you'll know whether to migrate today, what to keep in tsc, and how to ship faster cold starts in production.

What native TypeScript actually is in Node.js

Native TypeScript support in Node.js is not a TypeScript compiler. It is a type stripper, powered by the amaro module — a thin Node wrapper around the SWC transform engine. When Node loads a .ts, .mts, or .cts file, amaro removes type annotations, interfaces, type aliases, and other erasable syntax, replacing them with whitespace so that line numbers stay identical. The resulting JavaScript is then handed to V8.

The journey from --experimental-strip-types to default-on

Node 22 introduced `--experimental-strip-types`. Node 22.7 added `--experimental-transform-types` to handle enums and namespaces. Node 23 promoted strip-types to unflagged. Node 24 — the current LTS as of 2026 — makes type stripping the default for any .ts file. Transform-types remains opt-in because enums emit runtime code and that's a more invasive transformation.

What gets stripped versus transformed

Stripping is whitespace-only: `: number`, `interface User {}`, `as const`, generic parameters — gone, replaced by spaces. Transforming actually generates code: enums become objects with reverse mappings, namespaces become IIFEs, parameter properties become assignments. If you only use erasable syntax — the TC39 "Type Annotations" proposal subset — you don't need transform-types at all.

Comparison of TypeScript runtime support across Node 22, Node 24, Bun, and Deno — focus card highlighting Node 24's stable strip-types support
Figure 1 — TypeScript runtime feature matrix: what each runtime handles natively without a build step.

Cold-start performance: type stripping vs the ts-node generation

The most immediate, measurable win from native type stripping is cold-start time. ts-node spins up a full TypeScript compiler on every boot. tsx and SWC-based loaders skip type-checking but still parse and emit. Native strip-types lives inside Node itself, so the overhead is closer to a no-op.

What the numbers look like

On a basic Express server (~600 LoC), the cold-start gap is roughly 9× between ts-node and `node --strip-types`. For serverless functions — where every cold start is billed and user-facing — this is the difference between sub-200ms and 1.4 seconds. The interactive chart below lets you compare four loaders head-to-head against the native runtime.

Figure 2 — Interactive: cold-start time across Node.js TypeScript loaders. Hover bars to see exact milliseconds.

The 6 syntax rules you must follow

Type stripping is fast because it refuses to be a compiler. That means the TypeScript subset you can use is smaller than what tsc accepts. Most teams discover the restrictions on their first migration day — here are the rules in priority order.

Rule 1: no enums (unless you opt into transform-types)

`enum Direction { Up, Down }` requires real code generation. Without `--experimental-transform-types`, it throws at load. Use `as const` objects instead — they're erasable, smaller, and tree-shake better.

Rule 2: no namespaces with runtime members

Pure type-only namespaces work (the types get stripped). Namespaces that export values are runtime code and need transform-types. ES Modules have been the right answer here for years anyway.

Rule 3: import .ts files explicitly

When importing relative modules, write the .ts extension: `import { db } from './db.ts'`. Node will not resolve a bare specifier `./db` to a TypeScript file. This breaks habits but matches how ESM has always worked.

Pipeline diagram showing how Node.js with --strip-types processes a TypeScript file: app.ts to amaro to app.js to V8 to running process
Figure 3 — The execution pipeline: from source.ts to a running Node process, without tsc or esbuild.

Type-checking moves to CI, not the runtime

The biggest mental shift for teams adopting native TS is that the runtime will run broken types. amaro is not aware of your tsconfig.json — it strips, it does not validate. A function declared `(x: number) => void` will happily accept a string at runtime. This is by design.

The minimal safe setup

Run `tsc --noEmit` in CI on every push. Keep your editor's TypeScript Language Server running locally. With those two gates in place, you get the same safety guarantees as the old setup with none of the runtime cost.

package.json
// package.json scripts that work with native --strip-types
{
  "scripts": {
    "dev": "node --watch --env-file=.env src/server.ts",
    "start": "node --env-file=.env src/server.ts",
    "typecheck": "tsc --noEmit",
    "test": "node --test src/**/*.test.ts",
    "lint": "eslint . --ext .ts"
  },
  "engines": { "node": ">=24.0.0" }
}
⚠️Warning
Type stripping does NOT type-check. If you ship to production without running `tsc --noEmit` in CI, broken types will reach customers. Treat tsc as a linter — fast, fail-fast, and required for merge.
Figure 4 — Interactive radar: how Node 22, Node 24, Bun, and Deno score across seven TypeScript dimensions.
Ready to build your team?

Hire Pre-Vetted Node.js Developers

Skip the months-long search. Our exclusive talent network has senior Node.js experts ready to join your team in 48 hours.

Migrating an existing ts-node project in five steps

Most production codebases can move off ts-node in an afternoon. The mechanical work is small; the discipline is in the CI changes.

Step-by-step migration

First, bump the engines field to Node 24. Second, add explicit .ts extensions to relative imports — most editors will do this with a single refactor. Third, replace `enum` declarations with `as const` objects. Fourth, swap the dev script from `ts-node-dev` to `node --watch app.ts`. Fifth, add `tsc --noEmit` as a CI step if it isn't there already.

🚀Pro Tip
Use an ESLint rule to enforce explicit extensions: `import/extensions: ["error", "ignorePackages", { "ts": "always" }]`. This catches every bare `./db` import before it reaches a reviewer.

If you're scaling a Node.js team to take on a migration like this, HireNodeJS connects you with senior backend engineers who have done this exact upgrade in production — typically within 48 hours.

When to stay with a bundler

Native TS is a fantastic default — but it's not the right tool for every shape of project. Three scenarios still favour a build step in 2026.

JSX and React Server Components

Node 24 does not strip JSX. If you run a Next.js, Remix, or Astro app, you still need the framework's bundler. The win there is on the API/worker side — any process that doesn't render JSX can drop the bundler.

Path aliases via tsconfig

amaro ignores `compilerOptions.paths`. If your codebase relies on `@app/*` aliases, you need tsc-paths, tsx, or relative imports. Many teams use this migration as the moment to refactor to relative or workspace imports.

Heavy decorator use

If you're on NestJS or TypeORM with experimental decorators, stay on tsc or SWC for now. The TC39 Stage 3 decorator proposal is supported in transform-types mode, but the legacy `experimentalDecorators: true` flag is not.

Teams running NestJS-heavy stacks still benefit from native TS for their auxiliary services — workers, cron jobs, CLI tools. Explore Node.js engineers with NestJS depth for projects where the main app stays on a compiled toolchain.

Production deployment patterns

Once you've adopted native TypeScript locally, your Docker image, CI pipeline, and observability stack get noticeably simpler. Three patterns hold up well in production.

Single-stage Docker builds

You no longer need a `build` stage to emit JS into `dist/`. Your Dockerfile shrinks to a single FROM, an npm ci, and a CMD that runs the .ts entry directly. Image layers compress better and rebuilds are faster.

Dockerfile
# Single-stage Dockerfile for native --strip-types
FROM node:24-alpine
WORKDIR /app

# Install deps with reproducible lockfile
COPY package.json package-lock.json ./
RUN npm ci --omit=dev

# Copy source (no dist/ — Node runs .ts directly)
COPY src ./src
COPY tsconfig.json ./

# Type-check at build time (fail-fast)
RUN npx tsc --noEmit

ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "--enable-source-maps", "src/server.ts"]
💡Tip
Add `--enable-source-maps` to every production CMD. Without it, stack traces point at stripped JS lines instead of your TypeScript source — fine for hot paths, painful for incident response.

Serverless functions on Lambda and Cloudflare Workers

On AWS Lambda with the Node 22+ runtime, a .ts handler runs without a build step — see our Node.js on AWS Lambda guide for the full deployment recipe. For latency-sensitive APIs the 200ms-class cold start can pay for itself in one Black Friday.

Hire Expert Node.js Developers — Ready in 48 Hours

Adopting native TypeScript is mostly mechanical, but you still need engineers who understand the trade-offs: enum migration, source-map debugging, CI gates, and what to keep on a bundler. HireNodeJS.com specialises exclusively in Node.js talent — every developer is pre-vetted on real-world production projects, API design, runtime internals, and modern toolchains.

Unlike generalist platforms, our curated pool means you speak only to engineers who live and breathe Node.js. Most clients have their first developer working within 48 hours of getting in touch. Engagements start as short-term contracts and can convert to full-time hires with zero placement fee.

💡Tip
🚀 Ready to scale your Node.js team? HireNodeJS.com connects you with pre-vetted engineers who can join within 48 hours — no lengthy screening, no recruiter fees. Browse developers at hirenodejs.com/hire

The bottom line

Native TypeScript in Node.js is no longer experimental — it's the new baseline for greenfield Node projects in 2026. If your codebase uses erasable syntax, ES Modules, and runs outside a JSX bundler, you can drop ts-node today and reclaim seconds from every cold start. Keep tsc as a CI lint. Run `--enable-source-maps`. Migrate enums to `as const`. The rest is muscle memory.

For everyone still on a tsc dist/ pipeline: the migration is now small enough that you should schedule it for the next sprint. The savings compound — faster local feedback, simpler Docker images, lower Lambda bills, and fewer moving parts in your supply chain.

Topics
#Node.js#TypeScript#Type Stripping#Node 24#Performance#DevOps#Serverless

Frequently Asked Questions

What is Node.js native TypeScript support?

It's built-in type stripping that lets Node run .ts files directly. The runtime removes type annotations using the amaro module, then hands plain JavaScript to V8 — no tsc or bundler required.

Is --experimental-strip-types still experimental in 2026?

No. Node 23 unflagged it and Node 24 made type stripping the default behaviour for .ts files. The `--experimental-transform-types` flag is still needed for enums and namespaces.

Does native TypeScript type-check my code at runtime?

No. Native type stripping is whitespace-only — it never validates types. You must run `tsc --noEmit` in CI to catch type errors before they ship.

Will my existing ts-node project work with node --strip-types?

Mostly. You'll need to add explicit .ts extensions to relative imports, replace enums with `as const` objects, and skip tsconfig path aliases unless you keep a bundler.

How much faster is the cold start compared to ts-node?

On real Express servers, cold starts drop from around 1.4 seconds with ts-node to 200ms with `node --strip-types` — roughly 7×–9× faster. The gap is larger on serverless cold paths.

Should I still use TypeScript for my Node.js project?

Yes. The runtime change doesn't affect editor IntelliSense, refactoring, or CI type-checking. Native TS makes TypeScript easier to adopt, not less valuable.

About the Author
Vivek Singh
Founder & CEO at Witarist

Vivek Singh is the founder of Witarist and HireNodeJS.com — a platform connecting companies with pre-vetted Node.js developers. With years of experience scaling engineering teams, Vivek shares insights on hiring, tech talent, and building with Node.js.

Developers available now

Want a TypeScript + Node.js expert on your team?

HireNodeJS connects you with pre-vetted senior Node.js engineers fluent in modern TypeScript, serverless, and runtime internals — available within 48 hours. No recruiter fees, no lengthy screening.