-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Tuple types accepting incorrect data #19463
Comments
The type of It is arguable though when the array is fresh, it should follow the same rules as #3823 for objects. |
Think of it like this interface Tuple1<T> extends Array<T> {
0: T;
}
interface Tuple2<T, U> extends Array<T | U> {
0: T;
1: U;
}
declare let a: Tuple1<string>;
declare let b: Tuple2<string, string>;
a = b; // works, 'b' is also viewed as a `string[]` with a `0: string` |
See also: #6229 |
Did you make some specific decision to untype arrays then, compared to normal types? I don't see why this is any different from:
... which compile errors as you'd expect. If this is intended typescript behavior permanently, then we will have to excise all usage of tuples from our codebase and go to slower object-based types everywhere. This implementation is almost completely un-typesafe. :( |
TypeScript's original behavior allowed this. The motivating example for disallowing it was options-bag-style APIs where people were misspelling optional properties. Are you frequently running into excess tuple errors? (edit: not being cheeky, I'm legitimately looking for motivating use cases) |
Yes, we just made a correction to our codebase to change over a hundred usages of tuples that were being used incorrectly. |
The question in my book is what the pros and cons of each way are. What are the pros of allowing you to do what feels like, to me, "invalid" assignments to tuples? I.e. why SHOULD it be allowed to do:
That feels like it's an engineer bug in 100% of circumstances, and if we have the ability to fix it with TSC, then we should. |
Actually that example is disallowed. Excess assignment slots only work when the excess values are assignable to one of the member of the tuple. 🤷♂️ let a: [ string, number ] = [ 'hi', 12345, 'foo' ]; // ok
let b: [string] = ['hi', 12345]; // bad
let c: [string | number] = ['hi', 12345]; // ok Personal opinion too, when the array is fresh, it should be strictly checked against the left hand, because as @deregtd indicates, how is that ever a desired situation? Especially considering how the following works: let a: [string, number] = ['hi', 12345];
let b: [string] = a; // not assignable
let c: [string|number] = a; // ok That, again, while maybe sound from a type system perspective, I can't see why the assignment to |
From #19536, we would like to consider one of two alternatives here:
|
#1 sounds perfect to me. The way we often use tuples, it's basically just a quick and strong dynamic type that doesn't require wrapping in an interface. |
See notes in #19585 |
My vote goes for freshness, unless the full Strict/Open length tuples proposal gets implemented. Working with non-aliasable tuples is just painful. It will lead to many overloads, which is hardly ideal. E.g. this is a Haskell library trying to provide uniform usage patterns for tuples of disparate arities: https://github.com/augustss/tuple. The implementation code consists of ugly, automatically generated type class instances (e.g. Select). I don't think we'd like to go in that direction. |
Should be fixed by #17765 |
TypeScript Version: 2.6.0-rc
Code
Expected behavior:
Error: [string, string] is not compatible with [string].
Actual behavior:
Compiles A-ok
The text was updated successfully, but these errors were encountered: