-
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
Defer resolution of true and false branches in conditional types #31354
Conversation
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at bb9c5c9. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at bb9c5c9. You can monitor the build here. It should now contribute to this PR's status checks. |
There are definitely significantly fewer types being created when the true and false branches are deferred. Compiling
Compiling
Compiling
Compiling
|
Probably fixes #31341 too. |
@ahejlsberg we should be able to defer the simplification to assignability checking, similar to indexed accesses, to keep the fixed use-cases functional. |
@ahejlsberg #31374 is open with what I suggested - perf impact (compared to this PR as-is) in |
…lification Simplify conditionals upon comparison, rather than instantiation
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 066e4b6. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 066e4b6. You can monitor the build here. It should now contribute to this PR's status checks. |
Type 'keyof B' is not assignable to type '"valueOf"'. | ||
Type 'string | number | symbol' is not assignable to type '"valueOf"'. | ||
Type 'string' is not assignable to type '"valueOf"'. | ||
Type 'string' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf" | keyof A'. |
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.
did keyof A
expand into... itself? o.O
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.
In the first keyof A
, A
is a substitution type. It then gets expanded into keyof (A & string)
which becomes the union that ends in keyof A
where A
is the actual type variable. Not ideal, but neither was the prior error message.
return getSimplifiedType(trueType, writing); | ||
} | ||
else if (isIntersectionEmpty(checkType, extendsType)) { // Always false | ||
return neverType; |
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.
Why wasn't this just a Debug.fail
?
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.
Because it can happen and is perfectly fine when it does. Or am I misunderstanding your question?
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.
BTW, the comment "Always false" here refers to when the condition of the conditional type is known to always be false. It doesn't imply that the if
condition is always false.
This PR restores our previous behavior of deferring resolution of the true and false branches of conditional types. This fixes the performance regression we were seeing with statement completion in projects using
styled-components
(performance is now similar to 3.3).Because resolution of the true and false branches is deferred, simplifications of conditional types of the formT extends xxx ? T : never
andT extends xxx ? never : T
only occur when the actual declarations of the conditional types are written with identical types in theT
position and typenever
in the other position (i.e. simplification doesn't occur when conditional types only match the pattern following instantiation). This shouldn't matter in practice as the types we really care about,Exclude
andExtract
, follow the pattern. For example, #28748 is still fixed.EDIT: Conditional type simplification now takes place in
getSimplifiedType
and we simplify to the same extent as before, so the above comment no longer applies.Fixes #31302.
Fixes #31341.