-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Treat intersection types as potential never
#47751
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
When the following conditions are satisfied, `isSimpleTypeRelatedTo(source, target)` returns true, which is false positive. - `strictNullChecks` is disabled - `source` is `undefined` - `target` is an empty intersection type which reduces to `never` by discriminants In this case, `isSimpleTypeRelatedTo()` should actually return `false`, which does *not* mean `source` doesn't relate to `target`, but rather tells the checker to further investigate their relation.
When types are checked if they are `never` by their `TypeFlags`, they must first be reduced, because intersection types of object-like types which reduce to `never` don't have `TypeFlags.Never`. See microsoft#36696 for details. When a function is declared to return such type and it doesn't contain any return statement or it only contains return statements without expression, the error messages are incorrect as the checker sees its return type as non-`never`. This commit takes into account that intersection types potentially reduces to `never` and improves error messages.
@@ -17815,6 +17815,8 @@ namespace ts { | |||
const t = target.flags; | |||
if (t & TypeFlags.AnyOrUnknown || s & TypeFlags.Never || source === wildcardType) return true; | |||
if (t & TypeFlags.Never) return false; | |||
// Intersection types that would be reduced to never may be passed as `target`, thus returning early. | |||
if (t & TypeFlags.Intersection) return false; |
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 isn't quite the right fix, I will put something up in a PR.
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.
Thanks for the review. Besides my fix not allowing empty array literals assigned to never[]
, is it not "quite the right fix" because it fails to catch cases where target
is a union of empty intersections that also reduce to never
? A bit of explanation or even pointers would be appreciated if you don't mind!
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.
Yes, one issue is that both unions and intersections can potentially reduce to never
, so both need to be excluded when --strictNullChecks
is disabled. But another issue is that any
should be assignable to anything, which is handled by a test later in the body of isSimpleTypeRelatedTo
. So the code can't just unconditionally return false
here.
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.
Thanks! I'll think about those logic more carefully next time.
@@ -32138,7 +32140,8 @@ namespace ts { | |||
} | |||
|
|||
const functionFlags = getFunctionFlags(func); | |||
const type = returnType && unwrapReturnType(returnType, functionFlags); | |||
const unwrappedType = returnType && unwrapReturnType(returnType, functionFlags); | |||
const type = unwrappedType && getReducedType(unwrappedType); |
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.
I think this is best covered in a separate PR since it is really an unrelated fix.
Fixes #46032
This PR fixes crashes and improves error messages when a function is declared to return a type alias that names an intersection type of object-like types that reduces to
never
.Besides #46032, there have been certain circumstances under which using such type aliases as functions' return type emits error messages different from using
never
directly (playground). This PR improves error messages so that they emit the same errors (aside from elaboration ofnever
intersections). This is actually not really related to #46032, so let me know if I should open a separate issue/PR.