-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Limit "type guards as assertions" behavior #10118
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
// is distinguished from a regular type by a flags value of zero. Incomplete type | ||
// objects are internal to the getFlowTypeOfRefecence function and never escape it. | ||
export interface IncompleteType { | ||
flags: TypeFlags; // No flags set |
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.
Since we have numeric literal types and enum literal types now, shouldn't this just be TypeFlags.None
or 0
? (Which would alleviate the need for the long explanatory comment above. And possibly allow you to remove some of the casts you have in the implementation.)
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.
TypeFlags
isn't a union enum type (because it contains non-literal initializers and is intended to be used as bit flags), so there is no TypeFlags.None
type. I could use 0
, but then it would be less obvious that flags
is overlaid on the similarly named property in Type
. Either way, the comment is still necessary.
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.
IDK, I think 0
carries more meaning; since you're using only a sentinel value for the member, encoding the sentinel value in the type seems like a good documentation choice. And 0
should still be assignable to TypeFlags
, so it should still overlay just fine, right?
👍 |
With #8548 we introduced the notion of "type guards as assertions". This has caused a steady stream issues as users are surprised by the arguably counter-intuitive effects. With this PR we limit type guards as assertions to only affect incomplete types in control flow analysis of loops. Effectively this makes type guards as assertions an implementation detail of the control flow analyzer that isn't observable in the final types computed by the checker, and #8548 is for all practical purposes revoked.
For example, we now handle the following from #9246 correctly:
Likewise we produce the expected
never
type in this example from #9869:Fixes #9246, #9254, #9260, #9869, #10087. (Yeah, it's been causing some confusion!)