Open Andarist opened 1 year ago
Isnāt this controlled by allowSyntheticDefaultImports
?
Yeah, Iām aware of this, but of course itās not a moduleResolution
issue. Really, itās something that module
should handle. I believe behavior differs between different bundlers, which is, in technical terms, a huge bummer. Whatās really bad, IMO, is that last I checked, Webpack does the Node behavior for .{m,c}js
files, but not the equivalent TS extensions, which violates a pretty core assumption we have about the substitutability of declaration files, TS files, and JS files. This is already on my radar to investigate soon.
If you ever need a hug... I'm here for you.
I forked https://sokra.github.io/interop-test to https://andrewbranch.github.io/interop-test, removed a bunch of import and export variations that werenāt super interesting to me (there are still a ton), and added .ts/.mts cases to esbuild and Webpack. I need to add similar TS cases to Rollup, and Iād like to add Parcel, Bun, and perhaps others. But it shows basically what weāve already established in this issue:
.mjs
files (that is, it always synthesizes a default; it doesnāt care about whether the target module has a __esModule
marker)..mts
files since it understands TypeScript out of the box. Webpack does not.At first, it struck me as odd that these bundlers voluntarily adopted interop restrictions that Node tried very hard to avoid, but couldnāt for technical reasons. But doing so is the best way for them to handle code written for Nodeāitās a cross-compatibility strategy. I think it would be best to push all bundlers toward doing this, if theyāre not already. But since TypeScript isnāt yet set up to model this behavior (without also adopting nodenext
module resolution), it seems inevitable that if we do, it will be toggleable with compiler options somehow. So even if we canāt get bundlers to be consistent between each other on whether they apply this Node-compat behavior, users will be able to configure TypeScript for whatever their bundler does.
However, itās not possible for us to model bundlers like Webpack that apply the Node-compat behavior to .mjs files, but not to .mts files. Thatās something weāll need to push for across the bundler/TS-runtime ecosystem (Iām assuming Webpack isnāt the only one that will need changes) before any TS option can work.
However, itās not possible for us to model bundlers like Webpack that apply the Node-compat behavior to .mjs files, but not to .mts files. Thatās something weāll need to push for across the bundler/TS-runtime ecosystem (Iām assuming Webpack isnāt the only one that will need changes) before any TS option can work.
I recall that you mentioned knowing about this issue for quite some time. Is there some tracking issue about this in webpack? Did their team comment on this anyhow in the past?
I donāt know; Iām in the process of figuring out exactly what to propose, and plan to talk to Sean soon. I havenāt mentioned it earlier because it was something I noticed in passing while focusing on module resolution, and needed to double check that I wasnāt just holding it wrong š„“
I opened https://github.com/webpack/webpack/issues/17288, and also am showing relevant results at https://andrewbranch.github.io/interop-test/#synthesizing-default-exports-for-cjs-modules
@Andarist do you remember how you originally encountered this issue, i.e. what libraries were involved?
@andrewbranch likely it comes from me and @emmatown trying to implement our library building scheme that is meant to avoid dual package hazard and to provide consistent module shape across formats. We ended up emitting an extra proxy files to work around it. Notice the _default
vs default
dance introduced here: https://github.com/preconstruct/preconstruct/pull/546
Bug Report
š Search Terms
moduleResolution bundler node webpack default namespace
š Version & Regression Information
moduleResolution: bundler
āÆ Playground Link
Repro case can be found here
š Actual behavior
When resolving a
.d.mts
file that proxies to.d.ts
in a CJS package withmoduleResolution: bundler
, TypeScript complains with an error like:The reason that it complains about it is that TypeScript is resolving
default
import as if the.d.ts
in this CJS package could export the "real" default export. webpack actually follows semantics coined by node and it loads the namespace object as thedefault
export of that "cjs file".So the type-level reality diverges there from runtime. At runtime, with webpack - it works exactly like it would work in node. TypeScript thinks that the intention was to load
module.exports.default
there though.š Expected behavior
I'm not exactly sure what's the expected behavior here because "resolving" like a bundler is quite under-specified and bundlers are not quite consistent when it comes to this. Even when we check this very same repro, we can see that I had to use
defaultIsModuleExports: true
in Rollup for it to behave the same. By default, Rollup behaves in the same way as TypeScript does.cc @andrewbranch