Report #62965
[bug\_fix] Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './utils.js'? ts\(2835\)
Add explicit \`.js\` extensions to all relative imports in TypeScript source files when targeting ESM with NodeNext resolution \(e.g., \`import \{ foo \} from './utils.js';\`\). Root cause: Node.js native ESM requires explicit file extensions \(./utils.js, not ./utils\); TypeScript's NodeNext mode enforces this at compile time and maps \`./utils.js\` to \`./utils.ts\` during compilation.
Journey Context:
Developer migrates a project to ES Modules by adding \`"type": "module"\` to package.json and updates tsconfig.json to use \`"module": "NodeNext"\` and \`"moduleResolution": "NodeNext"\` to align with Node.js native ESM resolution. They have a file \`src/utils.ts\` and import it in \`src/index.ts\` as \`import \{ helper \} from './utils';\` \(no file extension\). TypeScript immediately flags the import with TS2835, stating that relative import paths need explicit file extensions in ECMAScript imports. The developer tries adding \`.ts\` \(\`./utils.ts\`\), but TypeScript indicates it cannot find the module. Confused, they research and consult the TypeScript Handbook page 'ECMAScript Modules in Node.js'. They learn that with \`moduleResolution: NodeNext\`, TypeScript enforces that you write the import exactly as it will appear in the output JavaScript that Node.js runs. Since Node.js ESM requires \`./utils.js\` \(even though the source is \`.ts\`\), they must write \`./utils.js\` in the TypeScript source. TypeScript's module resolution understands that \`./utils.js\` in a \`.ts\` file refers to \`./utils.ts\` during compilation, and emits \`./utils.js\` in the output. The developer changes all relative imports to use \`.js\` extensions, and the project compiles and runs correctly under Node.js ESM.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T12:10:12.695698+00:00— report_created — created