-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set esModuleInterop to "true" by default #41139
Comments
I'll take this as a possibility but we have historically not changed commandline defaults unless the case for it was overwhelmingly strong. This might have the possibility to break people's programs and we would need some very good evidence that it was worth those people encountering that problem. |
@RyanCavanaugh Yeah, it's tricky, right now it's causing resentment among non-TS developers who are trying to cater TS users, so current situation is undesirable as well. (See eg also this Twitter thread with me and @mcollina on top of the above GitHub issues: https://twitter.com/matteocollina/status/1305953416217268226) |
An example where the current default causes confusion and makes people stick with the older non-recommended path: plantain-00/type-coverage#78 Also had this Twitter conversation with @Rich-Harris: https://twitter.com/rich_harris/status/1361839944453541892?s=21 |
I'm a bit wary of using |
@bmeck Can you elaborate a bit on this or provide a link which describes it? My impression was that |
It kind of does, but not enough to be completely compatible. Particularly how Given: // ./entry.ts
import * as asNamespace from './dep.js';
import asDefault from './dep.js';
console.log({
asDefault,
asNamespace
}); // ./dep.js
module.exports = {
__esModule: true,
default: 'prop named default'
}; Compiling to CommonJS will result in the following outputs: Node (after renaming $ node ./entry.mjs
{
asDefault: { __esModule: true, default: 'prop named default' },
asNamespace: [Module: null prototype] {
__esModule: true,
default: { __esModule: true, default: 'prop named default' }
}
} After TS: $ node ./out/entry.js
{ asDefault: 'prop named default',
asNamespace: { __esModule: true, default: 'prop named default' } } Namely, even with |
The #44501 seems to partially implement this as both its module types imply So anyone setting the A good solution for changing the default without breaking backwards compatibility, but may complicate the uptake of those new types, see eg: sindresorhus/tsconfig#8 |
@bmeck Looking at the documentation page for
So while the compiler was fixed to comply with the first point, the ESM spec, as you say, two helper functions was also added to increase compatibility (I guess with older TS-code?) Those two helpers seems to be these two ones in __importStar = function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
__importDefault = function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
}; And after compilation your code would roughly look like (assuming // ./entry.ts
const asNamespace = tslib.__importStar(require('./dep.js'));
const asDefault = tslib.__importDefault(require('./dep.js'));
console.log({
asDefault,
asNamespace
}); So I guess, what you're getting at is that you think these two helpers should not be there? |
I have no opinion on implementation, just that the example above shouldn't behave differently from Node pre/post running TS when trying to match Node. I do not think |
Double checked whether this actually shipped, and it did: TypeScript/src/compiler/utilities.ts Lines 6428 to 6438 in 2bcfed0
So anyone using Though: This isn't at all mentioned in the docs for |
I am strongly opposed to using Many people don’t understand the difference between
I believe users need to be more aware of the code they ship (not write) and its correctness. |
Search Terms
Suggestion
Change
esModuleInterop
from being an opt-in to instead be an opt-out, taking one step further towards deprecating the non-esModuleInterop
mode and makeesModuleInterop
the only supported mode going forward (which has to be the long term goal).Use Cases
When Typescript 2.7 introduced
esModuleInterop
almost 3 years ago it emphasized clearly that:esModuleInterop
is also a recommended option to set intsconfig.json
and when one runstsc --init
it gets set totrue
automatically.However, the fact that it still is opt-in makes that non-
esModuleInterop
mode is still very prevalent, which kind of works against the very problems it was meant to fix – as rather than having just the pre-esModuleInterop
functionality, modules now have to try to make things work across both options – and on top of that increasingly have to work with TS-validated JS.All in all, that causes problems: fastify/env-schema#17
And is hard to wrap ones head around: https://github.com/fox1t/modules-playground
Even if one really tries: fox1t/modules-playground#3
Checklist
My suggestion meets these guidelines:
esModuleInterop
, but it would make it easier to get TypeScript and JavaScript code to stay compatible with one anotheresModuleInterop
, but it would make it easier to get TypeScript and JavaScript code to stay compatible with one anotherDo not cause substantial breaking changes from TypeScript 1.0.
The text was updated successfully, but these errors were encountered: