module.exports = Entity is an alias, just like export = Entity#23570
Conversation
This breaks a couple of tests for previous workarounds. Fix in upcoming commits.
instead of basically copying the code myself.
| 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.
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.
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.
| merged.flags = merged.flags | SymbolFlags.ValueModule; | ||
| merged.exports = createSymbolTable(); | ||
| } | ||
| mergeSymbolTable(merged.exports, moduleSymbol.exports); |
There was a problem hiding this comment.
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.
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 assignmentsThere was a problem hiding this comment.
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.
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.
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. |
weswigham
left a comment
There was a problem hiding this comment.
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 = Entityshould create an alias the same way thatexport = Entitydoes in typescript. Doing this allows the type of a class to resolve correctly, for example.The PR has a couple of other changes.
getTypeFromImportTypeNodeneeds 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