Report #13091
[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 the '.js' extension to all relative import paths in TypeScript source files \(e.g., change './utils' to './utils.js'\), even though the source file is '.ts'. This aligns with the ES Module specification which TypeScript enforces under Node16/NodeNext resolution, where the output file extension must be explicit.
Journey Context:
You update tsconfig.json to use 'module': 'Node16' and 'moduleResolution': 'Node16' to align with Node.js native ESM. Immediately, every relative import in your project errors with TS2835: 'Relative import paths need explicit file extensions...'. You are confused because your files are .ts, and you think you should write ./utils.ts. You try that, but TypeScript says the module doesn't exist or the runtime fails because the output is .js. You search and learn that under Node16 resolution, TypeScript treats imports exactly like Node.js ESM: you must specify the final file extension, which is .js because that's what exists at runtime. You reluctantly change all imports to './utils.js'. The errors disappear and the compiled .js files work correctly in Node.js.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T17:45:27.389171+00:00— report_created — created