Back to Knowledge Hub

Node.js + TypeScript in 2025: Built-In "Type Stripping" Isn’t Full TypeScript

Node.js can now run TypeScript directly—but there's a huge asterisk. Here's exactly what works, what breaks, and how to choose.

In This Article
  1. What "type stripping" means (and doesn't)
  2. Erasable vs non-erasable syntax
  3. Recommended tsconfig from Node's docs
  4. ESM vs CJS: you can't cheat it
  5. When to avoid type stripping
  6. Full TypeScript support with tsx
  7. Practical recipes you can copy/paste

Node.js can now run TypeScript directly—but there's an asterisk so big it should be on the homepage:

Node's built-in TS support is primarily type stripping, not full TypeScript compilation.

Node's own docs say there are two approaches: use a third-party package for full TypeScript features (including tsconfig.json), or use built-in support for lightweight type stripping.

What "type stripping" means (and what it doesn't)

Type Stripping: What It Does vs Doesn't
✅ What It Does❌ What It Doesn't Do
Execute TS files with erasable syntaxRead or apply your tsconfig.json
Replace types with whitespaceSupport path aliases
Run quickly without build stepDownlevel JS syntax (no "target ES2019")
Perform type checking
Critical Understanding

Type stripping is "run TS-like files," not "compile TS projects."

The key detail: some TS syntax isn't erasable

Node's docs call out that transforming non-erasable TS syntax (like enum declarations or parameter properties) requires JS code generation and needs a flag:

node --experimental-transform-types src/index.ts

To disable stripping entirely: --no-strip-types

Example: erasable types (works with stripping)

// src/math.ts
export function add(a: number, b: number): number {
  return a + b;
}

// Run it:
node src/math.ts

Example: non-erasable types (needs transform flag)

// src/status.ts
export enum Status {
  Ok = 200,
  NotFound = 404,
}

// Run with transform:
node --experimental-transform-types src/status.ts

Recommended tsconfig from Node's docs

Node recommends TypeScript 5.8+ and provides a tsconfig template tuned for type stripping:

{
  "compilerOptions": {
    "noEmit": true,
    "target": "esnext",
    "module": "nodenext",
    "rewriteRelativeImportExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true
  }
}
Why These Options Matter
OptionPurpose
module: nodenextMatches Node's ESM/CJS behavior expectations
rewriteRelativeImportExtensionsAligns TS imports with Node runtime resolution
erasableSyntaxOnlyKeeps you from writing TS that requires compilation
noEmitFor "runtime execution only" scripts

ESM vs CJS: you can't cheat it

Node will not convert between module systems:

  • Want ESM? Use import/export
  • Want CommonJS? Use require/module.exports

ESM example (recommended going forward)

// src/index.ts
import { add } from "./math.js"; // extension matters
console.log(add(1, 2));

CJS example

// src/index.cts
const { add } = require("./math.cjs");
console.log(add(1, 2));

When you should NOT use type stripping

Type Stripping Decision Matrix
✅ Use Type Stripping When❌ Avoid Type Stripping When
Writing scripts/toolsYou rely on path aliases
You want fast iterationYou use decorators / emit transforms
Your TS stays "erasable only"You expect tsconfig to change runtime
You don't need path aliasesYou need consistent build artifacts
Important Limitation

Node explicitly states tsconfig.json is ignored and tsconfig-dependent features are intentionally unsupported.

Full TypeScript support: the tsx approach

Node's docs explicitly recommend using a third-party package for full support. The most popular choice is tsx:

Install

npm install --save-dev tsx

Run

npx tsx src/index.ts

# Or:
node --import=tsx src/index.ts

Practical recipes (copy/paste)

Recipe A: "Scripts-only TS" (type stripping style)

Best for: build scripts, tooling, small CLIs

// package.json
{
  "type": "module",
  "scripts": {
    "dev": "node src/index.ts",
    "dev:transform": "node --experimental-transform-types src/index.ts",
    "typecheck": "tsc --noEmit"
  }
}

Recipe B: "App TS" (tsx style)

Best for: apps/services needing real TS features

// package.json
{
  "type": "module",
  "scripts": {
    "dev": "tsx src/index.ts",
    "typecheck": "tsc --noEmit",
    "test": "node --test"
  }
}
Key Takeaways
  • Node's built-in TS is type stripping, not full compilation
  • tsconfig.json is intentionally ignored
  • Enums and parameter properties need --experimental-transform-types
  • Use tsx for full TypeScript support in production apps
  • Pick the simplest path that keeps DX + debugging healthy

Enjoyed this article?

Explore more in-depth guides and comparisons in our Knowledge Hub.