microsoft / tslib

Runtime library for TypeScript helpers.
BSD Zero Clause License
1.25k stars 126 forks source link

fix: default interop compat for "module" condition #179

Closed guybedford closed 1 year ago

guybedford commented 2 years ago

This adds default import interop compat when resolving using the "module" condition.

Many users are still expecting import tslib from 'tslib' to work, since this is supported for the CommonJS interface in both Node.js and browsers, but if building with the "module" condition outside of Webpack (eg as import map generators like JSPM do), this results in breaking the tslib interop.

It is always recommended for all exports conditions to provide the same interface. This decoration effectively provides the identical interfaces between the ESM and CJS forms of tslib, maximizing interop.

//cc @weswigham

guybedford commented 1 year ago

Yes, exactly.

Andarist commented 1 year ago

Many users are still expecting import tslib from 'tslib' to work

This package ships an import condition though so the default-related interop shouldn't be broken here in the first place (although perhaps it was with some prior versions of this package).

guybedford commented 1 year ago

The problem I had here is JSPM supports the "module" condition because it can support CJS loading ESM, but it uses Node.js-style interop for the "module" condition which then breaks down. In general JSPM will be moving away from the "module" condition now for this reason...

Andarist commented 1 year ago

My understanding of the module condition was always that the files referenced by it should be authored in ESM but still consumable by both require and import loaders since the tool through which it is consumed is capable of that (like a bundler). Based on that, I'm somewhat confused as to what kind of an interop is needed in this situation 🤔

guybedford commented 1 year ago

@Andarist this is because bundlers in implementing the module condition break Node.js-style interop by default since they use "bundler ESM interop" which is different. Remember import x from 'cjs' is always export default module.exports!

guybedford commented 1 year ago

All this to say, the default + NS pattern is a kind of approach that can work for best interop. Node.js does it with its core modules too.

Andarist commented 1 year ago

Remember import x from 'cjs' is always export default module.exports!

yeah, i know how this one goes but that's only when the 'cjs' package doesn't have an import condition. This one has that so I'm not exactly sure what kind of scenario this PR is fixing.