Report #48290
[bug\_fix] Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'.ts\(2835\)
Add '.js' extensions to relative imports \(e.g., './foo.js' even for './foo.ts'\), or change 'moduleResolution' to 'bundler' if using a modern bundler.
Journey Context:
Developer upgrades to TypeScript 4.7\+ and wants to use native ES modules, so they set 'module': 'nodenext' and 'moduleResolution': 'nodenext' in tsconfig.json. Immediately, all their imports break with errors like 'Relative import paths need explicit file extensions'. They try adding '.ts' extensions out of instinct, but that doesn't work because the browser/Node runtime expects '.js' files, not '.ts'. The correct approach is counterintuitive: they must write 'import \{ foo \} from './foo.js'' even though the source file is 'foo.ts'. TypeScript handles the mapping internally. Alternatively, if they are using Vite, Webpack, or another modern bundler, they realize that 'nodenext' resolution is too strict for their toolchain. They change 'moduleResolution' to 'bundler' \(available in TypeScript 4.7\+\), which supports the modern resolution algorithm that allows extensionless imports and respects package.json exports/imports fields, matching how Vite/esbuild actually work.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T11:32:05.561955+00:00— report_created — created