You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rest binding element should contextually type initializer as a tuple #1824
x and y are string | number | boolean because the rest element causes the contextual type to be an array. It seems like there is no reason for this. I think the contextual type here should be a tuple, so x would be number, y would be string, and z would be (string | boolean)[]
This will only matter when you're destructuring a tuple using spread operator--which, I contend, is going to be a very rare. Futhermore, if we did this sort of partial tuple destructuring, wouldn't you also expect z to be of type [boolean, string]? And wouldn't you expect to be able to put it back together as a tuple again by writing [x, y, ...z] as an expression?
Right now we have a simple rule that says whenever spread or rest is involved, the result is an array. I think anything beyond that gets very muddled.
I agree that spread should make the result an array, because we don't know what you did to the array (lengthwise or elementwise) before you did the spread. However, rest seems different. I think with rest, there is no information lacking, that would cause it to be unsafe to consider the contextual type a tuple.
To answer your questions about the above example:
Yes, z should have the type [boolean, string]
No, we should not allow the user to put the tuple back together using spread. We don't know what they did before the spread. So while it's intuitive, I don't think that's a good idea. Unless people are fine with that type hole, but I'd rather start without it.
I think doing this for rest, but not spread, is a sensible option.
Would we then switch and make z an array? So sometimes you get an array and sometimes a tuple. I think there is more complexity here than meets the eye for practically zero gain. I just don't think it is a meaningful real world scenario and I'd rather have the simple rule.
In that case, z would be a tuple of length 0, which happens to degenerate to undefined[], but I don't think there's anything wrong with that... provided we change our way of detecting tuple types so that it checks a bit, rather than relying on the presence of a property named 0. Also note that if we did that, x and y would not get penalized.
I am not sure how anyone would gauge the benefits here. But the current rule about rest elements just doesn't seem to fit into our tuple story, and seems like changing it wouldn't cost us much.
Rereading this, I think we should actually do something different from what I mentioned. We should contextually type the RHS as a tuple, but then z should always be an array that matches the array being destructured. That way x and y have the expected types, and z behaves as it does today. What would be wrong with that?
Open question over whether this is the right thing to do or not, versus its priority relative other things (and our inability to change this if we decide to do it later)
Thanks. I will also point out that this situation is not as rare as it may seem, if you consider that the binding pattern can be a parameter, and the array literal can be an argument.
Activity
ahejlsberg commentedon Jan 27, 2015
This will only matter when you're destructuring a tuple using spread operator--which, I contend, is going to be a very rare. Futhermore, if we did this sort of partial tuple destructuring, wouldn't you also expect z to be of type
[boolean, string]? And wouldn't you expect to be able to put it back together as a tuple again by writing[x, y, ...z]as an expression?Right now we have a simple rule that says whenever spread or rest is involved, the result is an array. I think anything beyond that gets very muddled.
JsonFreeman commentedon Jan 28, 2015
I agree that spread should make the result an array, because we don't know what you did to the array (lengthwise or elementwise) before you did the spread. However, rest seems different. I think with rest, there is no information lacking, that would cause it to be unsafe to consider the contextual type a tuple.
To answer your questions about the above example:
[boolean, string]I think doing this for rest, but not spread, is a sensible option.
ahejlsberg commentedon Jan 28, 2015
What about
Would we then switch and make z an array? So sometimes you get an array and sometimes a tuple. I think there is more complexity here than meets the eye for practically zero gain. I just don't think it is a meaningful real world scenario and I'd rather have the simple rule.
JsonFreeman commentedon Jan 28, 2015
In that case, z would be a tuple of length 0, which happens to degenerate to
undefined[], but I don't think there's anything wrong with that... provided we change our way of detecting tuple types so that it checks a bit, rather than relying on the presence of a property named 0. Also note that if we did that, x and y would not get penalized.I am not sure how anyone would gauge the benefits here. But the current rule about rest elements just doesn't seem to fit into our tuple story, and seems like changing it wouldn't cost us much.
RyanCavanaugh commentedon May 4, 2015
Existing behavior matches general pattern of not inferring a tuple type when none was written
JsonFreeman commentedon May 4, 2015
Rereading this, I think we should actually do something different from what I mentioned. We should contextually type the RHS as a tuple, but then z should always be an array that matches the array being destructured. That way x and y have the expected types, and z behaves as it does today. What would be wrong with that?
RyanCavanaugh commentedon May 4, 2015
Open question over whether this is the right thing to do or not, versus its priority relative other things (and our inability to change this if we decide to do it later)
JsonFreeman commentedon May 5, 2015
Thanks. I will also point out that this situation is not as rare as it may seem, if you consider that the binding pattern can be a parameter, and the array literal can be an argument.
RyanCavanaugh commentedon May 19, 2015
Doesn't seem to be coming up in real code.