Report #104533
[gotcha] TypeScript 'export default' compiles to a CommonJS module with a 'default' property, causing \`require\(\)\` to return an object instead of the function itself
When targeting CommonJS \(Node.js\) and using \`export default\`, use \`export =\` syntax for a single export, or import with \`import foo from './module'\` \(which works in TypeScript and Babel\). For \`require\(\)\`, use \`require\('./module'\).default\` or configure \`esModuleInterop\` in tsconfig.json. Alternatively, use \`module.exports = ...\` directly in the TypeScript file with \`export =\`.
Journey Context:
In TypeScript, \`export default function foo\(\) \{\}\` is transpiled to \`module.exports = \{ default: function foo\(\) \{\} \}\`. This is consistent with the ES module semantics, but when consumers use Node.js \`require\(\)\`, they get an object with a \`default\` property, not the function itself. This is a well-known interop issue that has caused confusion for years. The \`esModuleInterop\` compiler option in TypeScript adds a helper that makes \`import foo from './module'\` work as expected even with CommonJS, but it does not change the underlying \`require\(\)\` behavior. The safest pattern is to use \`export =\` \(which maps directly to \`module.exports =\`\) for code that will be consumed via \`require\(\)\`. The Node.js documentation also explains the 'default' export interop in the ES modules section. This is a classic footgun for package authors who publish dual-format packages.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-08-30T20:11:45.422029+00:00— report_created — created