-
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
Discriminate contextual types #19733
Discriminate contextual types #19733
Conversation
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.
This is a cool fix! A couple of requests:
src/compiler/checker.ts
Outdated
return type && getApparentType(type); | ||
let contextualType = getContextualType(node); | ||
contextualType = contextualType && getApparentType(contextualType); | ||
if (contextualType && contextualType.flags & TypeFlags.Union && isObjectLiteralExpression(node)) { |
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.
invert this I think
src/compiler/checker.ts
Outdated
contextualType = contextualType && getApparentType(contextualType); | ||
if (contextualType && contextualType.flags & TypeFlags.Union && isObjectLiteralExpression(node)) { | ||
let match: Type | undefined; | ||
propLoop: for (const prop of node.properties) { |
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.
this code is almost exactly the same as the also-highly-questionable findMatchingDiscriminantType
. The only real difference, I suspect, is that this code doesn't bail if (type === match)
. Two things:
- Can you harmonise the two code paths so there's only one
findMatchingDiscriminantType
?
2.It's quite possible that the excess-property usage and union-error usage would both benefit from the(type === match)
addition, so it could be that you can just swap out the existing body for this code. - Three things! Using
findMatchingDiscriminantType
is slow, and only makes the compiler faster because it eliminates unions early on. Can you test performance with 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.
findMatchingDiscriminantType
operates on type members (andfindMatchingDiscriminantType
directly usesisRelatedTo
), this operates on an actual node tree (as most contextual type operations do), so sadly I don't think they can be merged (without a bunch of inefficient abstractions over weather you're getting symbols from types or nodes and such)- Sure, I'll try modifying
findMatchingDiscriminantType
, too; but I don't think it'll show up in much unless we add a test case where multiple fields are capable of acting as a discriminant for an object and discriminate to the same types. 🐱 - Sure, will do.
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 hey, waddoyaknow, we already do have a test (excessPropertyCheckWithUnions
) improved by changing findMatchingDiscriminantType
. Neat.
@sandersn As far as overall perf goes, this has no real effect on any codebase in our perf suite:
|
This was split from #19587, and the idea originated from a comment on #19322 (and then the code moved directly into
getApparentTypeOfContextualType
instead ofgetContextualThisParameterType
so as to be more general), and should be merged after #19587. The primary baseline changes will be visible in tests added in that PR; however there are some small changes already visible here because we toss out uninteresting contextual types earlier based on members we know the type of.This causes a few things:
this
types are discriminated based on the other members you wrote; meaning methods in objects contextually typed by something now have thethis
type of only the discriminated member you've indicated, if possible. (This is the primary benefit the tests in the other PR can show)