René's URL Explorer Experiment


Title: `esModuleInterop` and `allowSyntheticDefaultImports` in TypeScript 6.0+ · Issue #62529 · microsoft/TypeScript · GitHub

Open Graph Title: `esModuleInterop` and `allowSyntheticDefaultImports` in TypeScript 6.0+ · Issue #62529 · microsoft/TypeScript

X Title: `esModuleInterop` and `allowSyntheticDefaultImports` in TypeScript 6.0+ · Issue #62529 · microsoft/TypeScript

Description: Acknowledgement I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion. Comment Related: #54500 https://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-inter...

Open Graph Description: Acknowledgement I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion. Comment Related: #54500 https://www.typescriptlang.org/docs/h...

X Description: Acknowledgement I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion. Comment Related: #54500 https://www.typescriptlang.org/do...

Opengraph URL: https://github.com/microsoft/TypeScript/issues/62529

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`esModuleInterop` and `allowSyntheticDefaultImports` in TypeScript 6.0+","articleBody":"### Acknowledgement\n\n- [x] I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.\n\n### Comment\n\nRelated:\n- #54500\n- https://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-interop.html\n\n## Background\n\nThese options come into play when compiling\n\n```ts\nimport x from \"./transpiled-cjs\";\nconsole.log(x);\n```\n\nto CommonJS, where `./transpiled-cjs` is also a CommonJS module. With both options off, the emit of the above is:\n\n```js\nconst transpiled_cjs_1 = require(\"./transpiled-cjs\");\nconsole.log(transpiled_cjs_1.default);\n```\n\nIf `\"./transpiled-cjs\"` was compiled from ESM syntax with a default export, this works perfectly—a default import resolves to a default export. But now, let’s say we install an npm package that exposes the following CommonJS module:\n\n```js\nmodule.exports = function sayHello() {\n  console.log(\"Hello\");\n};\n```\n\nHow are we supposed to import this? It has no `default` property, so `cjs_1.default` is `undefined`. We could perhaps use a namespace import:\n\n```ts\nimport * as x from \"cjs-pkg\";\n```\n\nbecause it compiles to\n\n```js\nconst x = require(\"cjs-pkg\");\n```\n\nWhile this works at runtime, it breaks ESM semantics, because a namespace import in real ESM always resolves to a namespace-like object with no signatures. If we want to be able to use a CommonJS module that defines a single, non-namespacey `module.exports` from a transpiled ES module, it seems like we _have_ to be able to use a default import for it. So in summary, a transpiled default import\n\n1. needs to resolve to the `module.exports` of “true” CJS modules, and\n2. needs to resolve to the `module.exports.default` of ESM-transpiled-to-CJS modules.\n\nTo achieve this, the JavaScript community converged long ago on the convention of defining an `module.exports.__esModule` property in files that were transpiled from ESM to CJS:\n\n```js\nObject.defineProperty(module.exports, \"__esModule\", { value: true });\nexports.default = 42;\n```\n\nThis allows compilers to implement a default import that checks the `__esModule` flag in order to determine whether to return `module.exports` or `module.exports.default`:\n\n```js\nvar __importDefault = (this \u0026\u0026 this.__importDefault) || function (mod) {\n    return (mod \u0026\u0026 mod.__esModule) ? mod : { \"default\": mod };\n};\nconst transpiled_cjs_1 = __importDefault(require(\"./transpiled-cjs\"));\nconsole.log(transpiled_cjs_1.default);\n```\n\n**This improved emit is the primary thing `esModuleInterop` does.** The option `allowSyntheticDefaultImports` goes hand in hand with it—when enabled, the type checker is aware that _sometimes_ a default import can resolve to `module.exports`, and will try to figure out whether that’s the case by looking at the types of the module being imported.\n\n```ts\nimport x from \"cjs-pkg\";\n// with allowSyntheticDefaultImports, the compiler will resolve types for cjs-pkg\n// and try to guess whether the JS file has `__esModule` defined or not. In other words,\n//\n//     return (mod \u0026\u0026 mod.__esModule) ? mod : { \"default\": mod };\n//                                      ^^^   ^^^^^^^^^^^^^^^^^^\n//              will we take this branch ^ at runtime, or ^ this one?\n```\n\n## Some sweeping conclusions based on these facts\n\n1. **`allowSyntheticDefaultImports` without `esModuleInterop` or vice versa should never have been allowed.** `allowSyntheticDefaultImports` came first in order to support type checking behavior that would reflect the runtime behavior of Babel and Webpack. When `esModuleInterop` was added later, it implied `allowSyntheticDefaultImports`, but each option was still allowed to be set independently.\n2. **`esModuleInterop` should not be an option; it should be our standard emit.** The JavaScript ecosystem has universally agreed that an ESM default import resolves to `module.exports` for true CJS modules.\n3. **Correct type checking behavior depends on accurately determining whether the target module is a CJS module with `__esModule`.** Because TypeScript usually analyzes declaration files instead of the JavaScript that will get loaded at runtime, it’s possible for us to be misled on both whether a module is ESM or CJS and whether it has `__esModule`.\n\n## Guessing whether a module has an `__esModule` marker\n\nWhen we’re misled about whether a declaration file represents an ES module or CJS module, that’s always the result of a configuration error of the kind that https://arethetypeswrong.github.io was made to diagnose and fix. But when we’re trying to figure out whether a CJS module has an `__esModule` marker based on its declaration file, there is some ambiguity of our own making. These are the current rules for determining whether a module was transpiled from ESM syntax (i.e., whether it has an `__esModule` marker):\n\n1. **If the file we’re looking at is actually JavaScript, we can just look for `__esModule`.**\n2. **If the file is a `.ts` (non-declaration) file, we know we’re going to emit `__esModule` to the JavaScript unless it uses `export =`.**\n3. **If a declaration file has an `export default`, it is assumed to be compiled from ESM.** This is a heuristic, but a decently good one—it holds for any `.d.ts`/`.ts` pair that was generated by us. It could go wrong if a hand-written declaration file uses `export default` to describe a `module.exports.default` member of a true CJS module, but that case is fairly rare—it merits being documented in DefinitelyTyped guidance if it’s not already.\n4. **If a declaration file explicitly declares `__esModule` in the typings, the JS is assumed to have it.** I’ve never seen this, but it makes sense.\n\nOtherwise, we assume the module is a true CJS module without `__esModule`. This is where the real ambiguity lies. A TypeScript file like\n\n```ts\nexport const x = 42;\nexport const y = 43;\n```\n\nwill emit as\n\n```ts\n// .js\n\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.x = 42;\nexports.y = 43;\n\n// .d.ts\nexport declare const x = 42;\nexport declare const y = 43;\n```\n\nIf these compilation outputs are imported into another project using `esModuleInterop`, the rules stated above result in the compiler assuming that the JS **does not have an `__esModule` marker**, thereby incorrectly allowing a default import:\n\n```ts\nimport mod from \"x-and-y\";\n//     ^^^ binds to `module.exports.default` (undefined) at runtime,\n//         but `module.exports` in the type system!\nconsole.log(mod.x, mod.y); // 💥 TypeError: Cannot read properties of undefined (reading 'x')\n```\n\nIn other words, when we don’t know whether a default import is valid or not, we silently allow it in order to be more permissive. The only way to plug this hole is to stop using `esModuleInterop`/`allowSyntheticDefaultImports`, but that also prohibits default imports when we _definitely know_ they would work.\n\n## Proposed solutions\n\n1. **Deprecate `esModuleInterop: false`.**\n2. In addition, do one of the following with `allowSyntheticDefaultImports`:\n   1. Deprecate it too, making it always-on. Do nothing about the type-checking hole described above.\n   1. Change `allowSyntheticDefaultImports` to mean “allow default imports _when it’s ambiguous whether they’re safe_.” Default imports that are definitely (or almost definitely, based on the heuristics above) safe would always be allowed. The option would essentially become a strictness option (with `false` being stricter than `true`).\n   1. Deprecate it and make ambiguously-safe default imports always an error. It could catch some false positives on hand-authored declaration files, but using named imports, a namespace import, or `import x = require(\"mod\")` are all viable workarounds on the importer side, and we could make a mass change to DefinitelyTyped to fix the most common false positives on the exporter side:\n      ```diff\n      - export declare const x: number;\n      - export declare const y: number;\n      + declare namespace mod {\n      +   const x: number;\n      +   const y: number;\n      + }\n      + export = mod;\n      ```\n      This declaration file style is currently disallowed by a longstanding and arguably misguided lint rule in DefinitelyTyped, but we could make this the new preference for disambiguating transpiled CJS from true CJS along with an automated one-time bulk migration.\n\nMy preference: test (iii) on top repos and consider. I’m torn between (i) and (ii) otherwise, as I think the type checking hole is unfortunate, but it’s also longstanding and doesn’t get many complaints, so it would be a shame for it to stand in the way of deprecating an option with a name as bad as `allowSyntheticDefaultImports`.","author":{"url":"https://github.com/andrewbranch","@type":"Person","name":"andrewbranch"},"datePublished":"2025-10-02T18:23:12.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/62529/TypeScript/issues/62529"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:76d314bd-de3f-9d06-5578-a10bdd1a712c
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idC23A:BCEAA:FDAE15:15BD2D9:6A62D6F1
html-safe-noncefb9268e7765efcdc6b66e238a421f8dbf4759302d85b8ba0219333b9525f72fc
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDMjNBOkJDRUFBOkZEQUUxNToxNUJEMkQ5OjZBNjJENkYxIiwidmlzaXRvcl9pZCI6IjkwMTgyNzkyNDEzNTczODM0MDkiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac5fcc364b49698ca29d15dae2cf19e9547da6d93078ffbba0337886a4664fd16b
hovercard-subject-tagissue:3478485085
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/microsoft/TypeScript/62529/issue_layout
twitter:imagehttps://opengraph.githubassets.com/0334259e0986291965618c02de2b1b7a3fcaf346a32c7c92791cf6d521adf5d5/microsoft/TypeScript/issues/62529
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/0334259e0986291965618c02de2b1b7a3fcaf346a32c7c92791cf6d521adf5d5/microsoft/TypeScript/issues/62529
og:image:altAcknowledgement I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion. Comment Related: #54500 https://www.typescriptlang.org/docs/h...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameandrewbranch
hostnamegithub.com
expected-hostnamegithub.com
Nonedf33b1b61ee7b9a0af988199bfc3503c9c1acafb1f1d40e1f140ea7c84f890dd
turbo-cache-controlno-preview
go-importgithub.com/microsoft/TypeScript git https://github.com/microsoft/TypeScript.git
octolytics-dimension-user_id6154722
octolytics-dimension-user_loginmicrosoft
octolytics-dimension-repository_id20929025
octolytics-dimension-repository_nwomicrosoft/TypeScript
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id20929025
octolytics-dimension-repository_network_root_nwomicrosoft/TypeScript
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
released41cd1bdb290013455c0ac430fa755621733f5eb
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/microsoft/TypeScript/issues/62529#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2FTypeScript%2Fissues%2F62529
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
Code QualityEnforce quality at mergehttps://github.com/features/code-quality
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2FTypeScript%2Fissues%2F62529
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=microsoft%2FTypeScript
Reloadhttps://github.com/microsoft/TypeScript/issues/62529
Reloadhttps://github.com/microsoft/TypeScript/issues/62529
Reloadhttps://github.com/microsoft/TypeScript/issues/62529
Please reload this pagehttps://github.com/microsoft/TypeScript/issues/62529
microsoft https://github.com/microsoft
TypeScripthttps://github.com/microsoft/TypeScript
Notifications https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Fork 13.6k https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Star 110k https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Code https://github.com/microsoft/TypeScript
Issues 5k+ https://github.com/microsoft/TypeScript/issues
Pull requests 21 https://github.com/microsoft/TypeScript/pulls
Actions https://github.com/microsoft/TypeScript/actions
Projects https://github.com/microsoft/TypeScript/projects
Models https://github.com/microsoft/TypeScript/models
Wiki https://github.com/microsoft/TypeScript/wiki
Security and quality 0 https://github.com/microsoft/TypeScript/security
Insights https://github.com/microsoft/TypeScript/pulse
Code https://github.com/microsoft/TypeScript
Issues https://github.com/microsoft/TypeScript/issues
Pull requests https://github.com/microsoft/TypeScript/pulls
Actions https://github.com/microsoft/TypeScript/actions
Projects https://github.com/microsoft/TypeScript/projects
Models https://github.com/microsoft/TypeScript/models
Wiki https://github.com/microsoft/TypeScript/wiki
Security and quality https://github.com/microsoft/TypeScript/security
Insights https://github.com/microsoft/TypeScript/pulse
#62567https://github.com/microsoft/TypeScript/pull/62567
esModuleInterop and allowSyntheticDefaultImports in TypeScript 6.0+https://github.com/microsoft/TypeScript/issues/62529#top
#62567https://github.com/microsoft/TypeScript/pull/62567
https://github.com/andrewbranch
Breaking ChangeWould introduce errors in existing codehttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Breaking%20Change%22
DiscussionIssues which may not have code impacthttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Discussion%22
SuggestionAn idea for TypeScripthttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Suggestion%22
TypeScript 6.0.0https://github.com/microsoft/TypeScript/milestone/218
https://github.com/andrewbranch
andrewbranchhttps://github.com/andrewbranch
on Oct 2, 2025https://github.com/microsoft/TypeScript/issues/62529#issue-3478485085
6.0 Deprecation List #54500https://github.com/microsoft/TypeScript/issues/54500
https://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-interop.htmlhttps://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-interop.html
https://arethetypeswrong.github.iohttps://arethetypeswrong.github.io
andrewbranchhttps://github.com/andrewbranch
Breaking ChangeWould introduce errors in existing codehttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Breaking%20Change%22
DiscussionIssues which may not have code impacthttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Discussion%22
SuggestionAn idea for TypeScripthttps://github.com/microsoft/TypeScript/issues?q=state%3Aopen%20label%3A%22Suggestion%22
TypeScript 6.0.0No due datehttps://github.com/microsoft/TypeScript/milestone/218
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.