Repository navigation
Runtime error with *esModuleInterop* when CJS module has an export named "default" #38540
Description
Activity
Findings
I have already spent quite a lot of time debugging the issue, here's what I found.
The issue only arises when the
__importStarhelper is used. One way to make that happen is to have an import that mixes default and named imports: utilities.ts#L44The actual problem is inside the
__setModuleDefaulthelper that__importStarcalls.That one is defined as:
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; });
Now if the module already has an export called
default, it will try to overwrite suchmodule.exports.default, which fails because said property is not configurable.Proposal
In my view,
__importStar/__setModuleDefaultshould only try to writemodule.exports.defaultif said property does not exist.While this is somewhat of a compromise:
- this behavior would be much preferable to outright crashing.
- I think we can safely assume that the reason for any modern CJS module to have a
defaultexport is that they expect us to use it as a default import. (Just like what happens without esModuleInterop.
I'll be happy to submit a PR as soon as this is accepted. Working branch: https://github.com/marcelltoth/TypeScript/tree/fix/safe-set-module-default
Reacted by Adam Grant, jwheeler-gs, Anton Kropp, Danil Roshko, Boopathi Rajaa, Justin Nelson and Ben SjobergReacted by Adam Grant and Anton Kropp- added a commit that references this issue
on May 13, 2020 Same issue here using Typescript v3.9.2 with Sequelize v5.21.8, which uses a "default" on their exports, which is causing TS to choke on: https://github.com/sequelize/sequelize/blob/master/lib/sequelize.js#L1356
Reverting back to v3.8.3 fixes this for us as an interim solution.
Reacted by Anton Kropp, Ben Sjoberg, Adam Lewandowski, 陈志南Michael Chan, Pranam Gurung and Shahaed Hasan- added a commit that references this issue
on May 14, 2020 This is unfortunate since the promise.all fixes in 3.9 we have been waiting on for a long time now. Are there any suggested workarounds (short of downgrading) that would allow us to move to 3.9 without getting bit by this (we are hitting it with axios and some other libraries as well)
I can confirm having this same issue using TS 3.9.2, so I'll also be reverting all my work to v3.8.3 till this closes
Anton Kropp (@devshorts) What I ended up with is to split my imports in a way so the compiler emits an
__importDefaultinstead of the__importStar.Axios for example does not export any constant but the default, all the rest are just types so you can do:
// instead of import axios, { SomeAxiosType } from 'axios'; // do this import axios from 'axios'; import type { SomeAxiosType } from 'axios';
But I'll submit a fix as soon as some maintainer approves this issue.
Reacted by ayal, Anton Kropp, Ben Sjoberg and Mirco Cipriani+1
Reacted by Marcell Toth and Heartlander+1
This seems to have some unfortunate interaction with jest and underscore, where it causes ~25% of our repos to fail unit test compilation. Downgrading typescript to 3.8 removes the failures.I managed to reduce it to a minimum jest test case that fails:
import * as underscore from 'underscore'; test('test', () => { underscore.uniq(['']); });With the output:
npx jest --config jest.json test/a.test.ts FAIL test/a.test.ts ● Test suite failed to run TypeError: Cannot redefine property: default at Function.defineProperty (<anonymous>) at test/a.test.ts:10:12 at __importStar (test/a.test.ts:18:5) at Object.<anonymous> (test/a.test.ts:1:1) Test Suites: 1 failed, 1 total Tests: 0 total Snapshots: 0 total Time: 8.556s(Yes, the line number are wrong, I don't know why. The source file is just 6 lines.)
Debugging beyond this is more than I can do right now though, so I'm not even sure if this should be reported to jest or typescript project. FWIW, at least I'm posting my findings hoping that it might help someone.Reacted by Justin Nelson, Olamide Olatunji, Anton Kropp, Ben Sjoberg and Jeffrey FlynnLooks like tslib had the same issue: microsoft/tslib#102
They fixed it by reverting to the previous behavior in tslib 1.x, and publishing the breaking change as 2.0. This means that another workaround for this issue is to add tslib ^1.13.0 as a dependency, then set
"importHelpers": truein tsconfig.json. (Note that I've only tested this on a very simple project, I'm not sure if using the old import helpers will break anything.)If this is working as intended, I hope that it can be reverted in 3.x and pushed back to 4.0, since it's a breaking change.
We're also running into this with the launchdarkly react-client-sdk. See launchdarkly/react-client-sdk#36.
Here is a another simple demonstration of the issue: https://github.com/joeldenning/typescript-esm-cjs-interop
- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on May 26, 2020 - addedBugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issueand removedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on May 27, 2020 DanielRosenwasser commented
on May 27, 2020 MemberMore actionsWe should have a fix at #38808. If you can pick up the build that was produced here and try it out, that'd really help give us some confidence that we can back-port it to 3.9.
Reacted by Marcell Toth and Sean MathesonDaniel Rosenwasser (@DanielRosenwasser) That build fixes the issue for me. Modules imported with the
__importStarhelper are no longer causing the "Cannot redefine property: default" error.The fix for this is released in 3.9.4, which is currently released to npm under the
devdist-tag.Reacted by Marcell Toth and juanjoseruiz- locked as resolved and limited conversation to collaborators
on Oct 21, 2025
TypeScript Version: 3.9.2 & 4.0.0-dev.20200512
Search Terms: __setModuleDefault, __importStar, redefine, ts-lib
Code
Check out the full example at https://github.com/marcelltoth/typescript-bug
File
dangerous-module.js(commonjs module)This is a pattern seen in real world, when the authors of CJS modules are trying to be nice with us TypeScript users. This way the module is nicely consumable from TS without esModuleInterop. The pattern is used by - for example - axios
I have esModuleInterop and therefore allowSyntheticDefaultImports turned on. Then in another file:
File
index.tsI build it via
tsc, then runnode dist/index.json the output.Expected behavior:
The code logs to the console.
Actual behavior:
It throws on the import line like so:
Playground Link: https://github.com/marcelltoth/typescript-bug
Related Issues: #37113