Report #51422
[bug\_fix] TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'.
Append the \`.js\` extension to all relative import specifiers, even when importing TypeScript files \(e.g., change \`import \{ foo \} from './foo'\` to \`import \{ foo \} from './foo.js'\`\). TypeScript will resolve \`./foo.js\` to \`./foo.ts\` during compilation, and the emitted JavaScript will contain the correct ESM specifier. Alternatively, if using a bundler like Vite or Webpack, change \`moduleResolution\` to \`"bundler"\` in \`tsconfig.json\`, which does not require explicit extensions. The root cause is that Node.js native ESM requires full specifiers including extensions, and \`node16\`/\`nodenext\` resolution modes enforce this at compile time to ensure runtime compatibility.
Journey Context:
You migrate your Node.js backend to native ESM by adding \`"type": "module"\` to \`package.json\` and updating \`tsconfig.json\` to use \`"module": "NodeNext"\` and \`"moduleResolution": "NodeNext"\`. You rename your files to \`.mts\` or keep \`.ts\` with the correct settings. You run \`tsc\` and are immediately blocked by \`TS2835\` on every relative import, such as \`import \{ helper \} from './helper'\`. You are confused because the file is \`./helper.ts\`. You try changing the import to \`./helper.ts\`, but TypeScript reports it cannot find the module. You search the error code and find documentation explaining that for ESM output compatibility, you must reference the file with the extension it will have at runtime \(\`.js\`\), not the source extension \(\`.ts\`\). You reluctantly change all imports to use \`.js\` extensions \(e.g., \`./helper.js\`\). The TypeScript compiler now successfully maps these to the \`.ts\` source files, and the emitted ESM in the \`outDir\` contains valid \`.js\` specifiers that run correctly in Node.js.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T16:47:58.791202+00:00— report_created — created