Skip to main content
This recipe corrects TypeScript import specifiers from the old tsc requirement of using .js extensions in source code to proper TypeScript extensions, making your code runnable by Node.js and other standards-compliant runtime environments.

What It Does

Transforms import specifiers to use correct file extensions:
  • No extension → .ts, .cts, .mts, .d.ts, .d.cts, .d.mts
  • .js.ts
  • .cjs.cts
  • .mjs.mts
  • .js.d.ts, .d.cts, .d.mts (for type-only imports)
  • Directory imports → ./directory/index.ts

Usage

This will modify your source code. Commit any unsaved changes before running.
The --experimental-import-meta-resolve flag is required for the codemod to resolve module paths correctly. Despite the name, this feature is stable in modern Node.js versions.

Examples

Basic Import Corrections

Before
After

Supported Cases

  • Missing extensions - Adds correct .ts, .cts, .mts, or .d.ts extensions
  • Incorrect extensions - Changes .js to .ts, .cjs to .cts, .mjs to .mts
  • Package.json subpath imports - Respects # imports defined in package.json
  • tsconfig paths - Resolves path aliases via @nodejs-loaders/alias
  • Directory specifiers - Converts ./dir to ./dir/index.ts
  • Type-only exports - Automatically adds type keyword where appropriate

TypeScript Configuration

After running this codemod, update your tsconfig.json:
Enable rewriteRelativeImportExtensions in your tsconfig:
tsconfig.json

Monorepo Usage

For monorepos, run the codemod within each workspace for best results:

Safety Features

The codemod doesn’t blindly replace extensions - it confirms each replacement actually exists on the filesystem.
  • File existence verification - Only applies changes when target files exist
  • Ambiguity detection - Skips cases where multiple valid targets exist (e.g., both foo.ts and foo.js)
  • Error logging - Reports ambiguous cases for manual review
  • Continues on errors - Skips problematic imports and continues processing
The codemod does not verify that imported modules contain the expected exports. Run your code after migration to catch any issues - Node.js will error if imports are incorrect.

Type Import Keywords

Node.js requires the type keyword on type-only imports. While this codemod handles most cases, some scenarios may require additional tooling: Run this codemod first, then apply one of these fixers if needed.

Why This Matters

TypeScript historically required .js extensions in import statements even when importing .ts files, creating a mismatch between source code and actual files. With Node.js native ESM support:
  • Import specifiers must match actual file names
  • Runtime environments need correct extensions to resolve modules
  • This enables running TypeScript directly with loaders or transpilers
  • Aligns with ECMAScript module standards