-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Use control flow to type CommonJS exports #42751
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
Use control flow to type CommonJS exports #42751
Conversation
This allows us to read our own output, plus the times when people manually write exactly the same pattern. Fixes #40555
Feels like something we could use CFA for, like how we track initializers for class properties through a constructor body. |
The problem with control flow is that it doesn't normally persist across aliases. It doesn't actually matter what the type of Edit: To use control flow, maybe I could create a structure to query and capture the type at the bottom of the file. Not sure how that would work either. |
I mean, analogously, the externally visible type of a constructor property is the one determined by CFA at the end of the conctructor, yeah? Not the union of the constructor-assigned types. |
Yeah; if we don't already have a CFA node at the end of the file (I think we should, though), you'd need to add one like we did for constructor properties. |
1. Could probably use a *lot* more tests. 2. getTypeOfAlias redoes some work from resolveAlias because it needs to not resolve the alias completely, just to its export.
src/compiler/checker.ts
Outdated
@@ -26429,7 +26448,10 @@ namespace ts { | |||
// accessor, or optional method. | |||
const assignmentKind = getAssignmentTargetKind(node); | |||
if (assignmentKind === AssignmentKind.Definite || | |||
prop && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { |
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.
Only change here is to exempt isDuplicatedCommonJSExport
so that it falls through to the autoType case below
src/compiler/checker.ts
Outdated
@@ -8359,7 +8374,10 @@ namespace ts { | |||
} | |||
|
|||
function getFlowTypeOfProperty(reference: Node, prop: Symbol | undefined) { | |||
const initialType = prop && (!isAutoTypedProperty(prop) || getEffectiveModifierFlags(prop.valueDeclaration) & ModifierFlags.Ambient) && getTypeOfPropertyInBaseClass(prop) || undefinedType; |
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.
No changes here, I just couldn't read it otherwise
This is a much bigger change, so
|
function a() { } | ||
exports.apply() | ||
~~~~~~~~~~~~~ | ||
!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. |
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.
Oh that's nice. 👍
@typescript-bot perf test this |
Heya @sandersn, I've started to run the perf test suite on this PR at 046bed9. You can monitor the build here. Update: The results are in! |
@sandersn Here they are:Comparison Report - master..42751
System
Hosts
Scenarios
|
1. Update the module.exports test to match the exports ones. 2. Add a test of evolving commonjs type. 3. Add a test of assignment as last statement. (1) exposed a bug that required a better synthetic reference. (3) exposed a bug that was most easily fixed by giving source files a `endFlowNode` like functions and setting it in the binder.
@typescript-bot perf test this |
Heya @sandersn, I've started to run the perf test suite on this PR at 6880763. You can monitor the build here. Update: The results are in! |
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
@sandersn Here they are:Comparison Report - master..42751
System
Hosts
Scenarios
|
Perf run: There's a lot of variance in the node 14 results, but it's both positive and negative. I don't think there's any real impact here.
|
(New changes to Typescript)[microsoft/TypeScript#42751] make it better at figuring out the type of `module.exports`. Unfortunately, it still gets confused by some bundler outputs, which is what the npm-naming rule uses to compare index.d.ts to find out if the types match the original JS well enough. This PR adds exemptions to the 7 packages that started failing after the linked Typescript PR was merged.
(New changes to Typescript)[microsoft/TypeScript#42751] make it better at figuring out the type of `module.exports`. Unfortunately, it still gets confused by some bundler outputs, which is what the npm-naming rule uses to compare index.d.ts to find out if the types match the original JS well enough. This PR adds exemptions to the 7 packages that started failing after the linked Typescript PR was merged.
This allows us to read our own output, plus the times when people manually write exactly the same pattern. It may also allow other patterns in the wild, although I need to look at the user test output to find out if that's the case.
Implementation notes
endFlowNode
property to source files in order to run control flow on the statements of a source file. Then I use this node to get the control flow type of an export from outside the file, when it's imported.Fixes #40555