Skip to content
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

Rest binding element should contextually type initializer as a tuple #1824

Closed
JsonFreeman opened this issue Jan 27, 2015 · 9 comments
Closed
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@JsonFreeman
Copy link
Contributor

var [x, y, ...z] = [0, "", true, ""];

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)[]

@JsonFreeman JsonFreeman added the Bug A bug in TypeScript label Jan 27, 2015
@ahejlsberg ahejlsberg added By Design Deprecated - use "Working as Intended" or "Design Limitation" instead Suggestion An idea for TypeScript In Discussion Not yet reached consensus and removed Bug A bug in TypeScript By Design Deprecated - use "Working as Intended" or "Design Limitation" instead labels Jan 27, 2015
@ahejlsberg
Copy link
Member

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
Copy link
Contributor Author

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:

  1. Yes, z should have the type [boolean, string]
  2. 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.

@ahejlsberg
Copy link
Member

What about

var [x, y, ...z] = [0, ""];

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
Copy link
Contributor Author

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
Copy link
Member

Existing behavior matches general pattern of not inferring a tuple type when none was written

@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision and removed In Discussion Not yet reached consensus labels May 4, 2015
@JsonFreeman
Copy link
Contributor Author

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 RyanCavanaugh added In Discussion Not yet reached consensus and removed Declined The issue was declined as something which matches the TypeScript vision labels May 4, 2015
@RyanCavanaugh RyanCavanaugh reopened this May 4, 2015
@RyanCavanaugh
Copy link
Member

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
Copy link
Contributor Author

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 RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision and removed In Discussion Not yet reached consensus labels May 19, 2015
@RyanCavanaugh
Copy link
Member

Doesn't seem to be coming up in real code.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants