-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Empty tuple type now meaningful (at least, in unions) #13126
Comments
Approved, accepting PRs. The type |
From @Aleksey-Bykov at his #13239 on what distinguishes tuples (like this 0-ary one):
To summarize compared to
My instinct had been to have a Interestingly, specifying length may address #6229. |
// ['syntax', true] => { 0: 'syntax', 1: true }
type Tup = ['syntax', true]
type T1<I> = Tup[I] // error
type T2<I extends number> = Tup[I] // error
type T2<I extends keyof Tup> = Tup[I] // OK
type T2<I extends number> = (Tup & { [k: number]: undefined })[I] // OK
Question based on that, also to @Aleksey-Bykov: would it not be unfortunate if dropping the index would mean tuples would even no longer match |
@tycho01 type Tuple2<A, B> = { 0: A, 1: B, length: 2 }
declare function mkTuple2<A, B>(a: A, b: B): Tuple2<A, B>;
declare function useArrayLike<T>(x: ArrayLike<T>): void;
useArrayLike(mkTuple2(1, 'hello')); On the other hand, an exact To be honest, I haven't thought over all consequences and edge cases. |
And here I thought that needed an index. Pretty cool!
Right. So the consequences of this one we know at least (#17765, see changed test files). |
To put discussions on a first-class
Edit: note that this issue also occurs if you even just tie tuples to |
Here's what I found from running the tests on a variant of #17765 that also makes tuples extend ReadonlyArray instead of Array. I have not run DefinitelyTyped yet, but may do so tomorrow. OverviewThere's not a lot of value from this change relative to the number of errors. It forces you to make your types a lot more precise, but doesn't find much more incorrect code than just adding a length property. Good
Bad
The code is correct here, the types are just not safe. In general, because tuples are limited, advanced usage will unsafely cast them to
type SpecDoc = [string, Snapshot, Json<AnyJS>];
type DirtySpecDoc = [string, Snapshot, Json<AnyJS>, 'local']; Then they use Ugly
|
@sandersn: thank you for summarizing; that's pretty insightful. Firebase example: |
I'm running definitely typed right now to find out what OO devs prefer (since I'm horrible at guessing that :). The only mutation right now is in a test that asserts "tuples are mutable", which is not indicative of actual usage. I don't think making array methods into tuple-type-altering methods is a great idea, even if it were possible, since I think it would only help a subset of cases. Surprisingly, disallowing |
Great, pretty curious as to the results! On tuple methods, my initial instinct is, when |
Definitely Typed catches a couple of good errors, and it exposes some limitations in type argument inference, return type inference and contextual typing, where the compiler gets a tuple type when it should be an array type, or vice versa. These bugs aren't the fault of the authors, but would have to be fixed before making this change. Good
Bad
let pairs: [string, number][];
assertEqual([['a', 1], ['b', 1]], pairs) This is a limitation of inference that is exposed by this change.
This is a mistake in contextual typing exposed by this change. Ugly
|
I wonder if the fake tuples predated tuple syntax. The If that's the total damage on DT for known length + |
Is this resolved by the recent addition of empty tuple types? |
I have a situation where the only valid states for a property are
[]
,[A]
, or[A, B, B]
, so I would like to define that property as[] | [A] | [A, B, B]
. But this gives the error "A tuple element list cannot be empty," and indeed I see that there were a few prior issues relating to the compiler having (incorrectly) allowed it in the past. It seems to me that now, between overloading and unions, this type is useful. Also useful in a typeguard:isEmpty<A>(values: A[]): values is [] { return values.length === 0; }
I suppose the most difficult part of it would be actually tracking that a given array is empty, so that it could be matched against that definition.
Per the checklist, the grammar is simple enough,
[]
in type positions, shouldn't have any issues with respect to JavaScript. I don't foresee any semantic issues except the above bit about actually recognizing empty arrays as such. The emit isn't affected at all, and compatibility shouldn't be an issue. I'm not rightly sure about the concerns raised in the Other section.The text was updated successfully, but these errors were encountered: