-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
allow narrowing to any sub-type-expression in type guards #6544
Comments
Just as a starting point for things we need in the proposal, there's no such thing as "partial assignability". |
I am lacking proper terminology sorry. Out of all possible combinations of types A, ..., Z using operations of
In other words: anything that, according to the type being assert, is possible should be able to be the target type of a custom type guard. |
I think what I'm hearing is that if you have a parameter whose type is an intersection type, the type predicate's type must be assignable to any one constituent of the intersection type? For example: // OK because A is assignable to (A | B)
declare function f1(x: (A | B) & C): x is A
// Error
declare function f2(x: (A | B) & C): x is number; |
to sure I got it... not only intersection, but union too:
here! I got it: any sub-type-expression (as long as we talk unions and intersections) of the type-expression being asserted against should be a valid target of a type guard:
|
You don't need a special rule for union types because it's already the case that |
Because narrowing is what type guards do! 😜 |
Any value that satisfies
A value of type However a value of type Isn't that the reason why |
@yortus I understand the mechanics of how it works now and you are right in what you saying. I am questioning the very premise that narrowing can't go beyond a member of a union type. I see no reason why it can't. What I am suggesting is that narrowing should be allowed to any sub-expression including lone terms. |
@Aleksey-Bykov maybe I get what you are saying, but I'm not sure. Do you mean that narrowing/type assertion should follow assignability rules sometimes, like: declare function f1(x: (A & B)): x is A; // error by narrowing rules
var ab: A & B;
var a: A = ab; // ok by assignability rules |
yes |
So if you want to narrow a variable of type |
The guard functions would be interesting: function isX(val: X&Y): val is X {
// ALWAYS TRUE: every value that satisfies X&Y also satisfies X
return true;
} |
in your example it is
this is what brought it up in the first place (#6538) type V = (X | Y) & Z | W
function isZ(v: V): v is Z {
}
Exactly, it's just a degenerate case. |
So why not do this instead: type V = (X | Y) & Z | W;
function isZ(v: V): v is (X | Y) & Z {...}
if (isZ(val)) {
// here we can treat val like a Z
} |
yes, you can do this way, the major points are:
|
Fair point. So while allowing narrowing |
Type guard returns must be a subtype because they introduce new properties in their guarded expressions, not remove them |
Currently
X & Y | Z
cannot be asserted as beingX
orY
separately in custom type guards (onlyX & Y
together), however there seem to be no reason why they can't be. #6538The text was updated successfully, but these errors were encountered: