Report #77279
[bug\_fix] The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. TS1479 \(or Cannot find module './foo.js' or its corresponding type declarations\)
Set \`module: "NodeNext"\` and \`moduleResolution: "NodeNext"\` in tsconfig.json, add \`"type": "module"\` to package.json, and use explicit \`.js\` extensions on all relative imports \(even for \`.ts\` source files\). Root cause: TypeScript 4.7\+ introduced \`NodeNext\` to strictly model Node.js's native ESM resolution rules, which require explicit file extensions \(no automatic \`index.js\` resolution\) and treat files as ESM only if they have \`.mts\` extensions or are in a \`"type": "module"\` scope; using \`module: "ESNext"\` without \`NodeNext\` resolution causes a mismatch between TS's expectations and Node's runtime behavior.
Journey Context:
A developer starts a fresh Node.js project, intending to use native ES Modules. They set \`module: "ESNext"\` in tsconfig.json \(old habit from frontend bundler days\). They write \`import \{ helper \} from './utils';\` \(no extension\) in \`src/index.ts\`. They add \`"type": "module"\` to package.json so Node treats \`.js\` as ESM. They run \`tsc\`. It compiles. They run \`node dist/index.js\`. It crashes: \`Error \[ERR\_MODULE\_NOT\_FOUND\]: Cannot find module '/project/dist/utils'\` \(note no extension\). Developer confused - \`tsc\` created \`dist/utils.js\`, why didn't it find it? They realize Node ESM requires explicit \`./utils.js\`, not \`./utils\`. They go back to source and change import to \`./utils.js\` \(even though the file is \`.ts\`\). \`tsc\` now complains: \`TS2835: Relative import paths need explicit file extensions in ECMAScript imports.\` Wait, that's the error they wanted\! Actually TS 4.7\+ with \`module: "NodeNext"\` enforces this at compile time. Developer realizes they should have used \`module: "NodeNext"\` and \`moduleResolution: "NodeNext"\` from the start. They change tsconfig. Now TS explicitly tells them to add \`.js\` extensions to all imports. They do. Code compiles. Node runs it successfully. Developer understands that \`NodeNext\` is a holistic mode that forces code to be Node-ESM-compliant at author-time, preventing runtime surprises.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T12:18:36.284449+00:00— report_created — created