-
Notifications
You must be signed in to change notification settings - Fork 12.8k
module.exports = Entity
is an alias, just like export = Entity
#23570
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
Conversation
This breaks a couple of tests for previous workarounds. Fix in upcoming commits.
instead of basically copying the code myself.
src/compiler/checker.ts
Outdated
@@ -8676,6 +8677,9 @@ namespace ts { | |||
if (moduleSymbol.flags & targetMeaning) { | |||
resolveImportSymbolType(node, links, moduleSymbol, targetMeaning); | |||
} | |||
else if (node.flags & NodeFlags.JSDoc && moduleSymbol.flags & SymbolFlags.Value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I ran your new test with the debugger, this clause wasn't executed, so it seems unnecessary (indeed, I can't figure out when you'd need it, with the binder fixed up); what prompted it? (Indeed - I deleted it and no tests failed, leading me to believe this may be a bit vestigial from before you fixed the binder)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I am just crazy, because I saw failures this morning when trying to get rid of this.
Except...I didn't just try to get rid of it, I tried to refactor it earlier in the function. So I guess it is indeed vestigial from my work yesterday.
src/compiler/checker.ts
Outdated
merged.flags = merged.flags | SymbolFlags.ValueModule; | ||
merged.exports = createSymbolTable(); | ||
} | ||
mergeSymbolTable(merged.exports, moduleSymbol.exports); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is subtly different - if you somehow bind an export=
and normal exports, this will merge the normal export with an export=
member of the same name (creating a merge symbol in the process), whereas previously the first symbol in won.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which, I guess in JS might actually be possible, since you can do
module.exports.x = 2;
class Foo {};
module.exports = Foo; // should hide all prior assignments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the exported thing that has to have a property named export=
for this to manifest, not the module. In what cases can the exported thing have export=
? I can't think of any. Namespaces don't exist in JS, and that's the only construct I am not sure about.
(Your example is a real problem, it's just not related to this change.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After much discussion and experimentation, it looks like I can move this merging code (added in #23228) into the binder as long as we correctly handle conflicts between property assignments names and contents of the export assignment (eg module.exports.x = ...
and module.exports = { x: ... }
.
However, that change is not trivial, so I want to put it in a separate PR so it doesn't block webpack PR webpack/webpack#7031 that is waiting on this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, I think I will revert it since it will be going away in the next few days anyway.
It is more correct and will go away in a few days.
Note that this code still doesn't work for class expressions (from Webpack): // in WebpackError.js
module.exports = class WebpackError extends Error {
constructor(message) {
super(message);
this.details = undefined;
Error.captureStackTrace(this, this.constructor);
}
inspect() {
return this.stack + (this.details ? `\n${this.details}` : "");
}
};
// in Dependency.js
class Dependency {
/** @return {null | (import("./WebpackError"))[]} */
getWarnings() {
return null;
}
} But it now works when exporting an alias: // in WebpackError.js
class WebpackError extends Error {
constructor(message) {
super(message);
this.details = undefined;
Error.captureStackTrace(this, this.constructor);
}
inspect() {
return this.stack + (this.details ? `\n${this.details}` : "");
}
};
module.exports = WebpackError |
Typescript behaves exactly the same way: 😿 // in first.ts
export = class Huh {
x = 1
}
// in main.ts
import Huh = require('./first')
declare var huh: Huh // should not error on type name Huh, but does |
@sandersn Which doesn't work mostly for the same reasons |
Yes, probably. It should work in TS too, unless there are weird problems with declaration emit. I don't think there are, but can you think of any? |
@sandersn erm.... Technically I don't think we parse |
In both JS and TS
OK, exported class expressions can now be used as types when imported. This works in both JS and TS. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the one comment I made in person about how unnamed classes aught to be fine (maybe wanna test that), but otherwise looks good.
Yep, works fine without a name. I totally forgot that importing the class would give it a name. |
module.exports = Entity
should create an alias the same way thatexport = Entity
does in typescript. Doing this allows the type of a class to resolve correctly, for example.The PR has a couple of other changes.
getTypeFromImportTypeNode
needs a special case for import types in JSDoc to avoid the "Module 'foo' does not refer to a type but is used as a type here" error.Fixes #23375