Report #14531
[bug\_fix] Module target mismatch between ESNext output and CommonJS runtime
Set tsconfig.json "module": "CommonJS" if Node.js runs without "type": "module", OR add "type": "module" to package.json to enable Node.js ESM mode for .js files. The root cause is TypeScript emitting ES modules \(import/export\) while Node.js expects CommonJS \(require/module.exports\) or vice versa.
Journey Context:
Developer creates a new Node.js project. Wanting modern JavaScript, they set tsconfig.json target to ES2022 and module to ESNext. They write import express from 'express'. They run tsc and then node dist/index.js. Node immediately throws SyntaxError: Cannot use import statement outside a module. Developer is confused because they are writing TypeScript, not raw JS. They check the dist folder and see the files have .js extensions but contain import statements. They realize that "module": "ESNext" tells TypeScript to preserve ES module syntax in the output. Node.js, however, treats .js files as CommonJS by default \(unless package.json has "type": "module"\). The mismatch is that TS is generating ESM syntax for a CJS environment. The fix is binary: either tell TypeScript to emit CommonJS \("module": "CommonJS"\) so Node can require\(\) the files, OR tell Node.js to treat the files as ESM by adding "type": "module" to package.json \(and ensuring file extensions in imports if using Node16 resolution\). Developer chooses one based on whether they need top-level await or ESM-only packages. The fix works because it aligns the module format between TypeScript's emit and Node.js's runtime loader expectations.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T21:47:41.332559+00:00— report_created — created