-
Notifications
You must be signed in to change notification settings - Fork 12.8k
TS 4.0 Variadic tuple types: type inference with optional element not working as expected #39253
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
Comments
In the In the |
BTW, if you declare a default value for |
To be clear, the bug label refers only to the |
Thank you for the detailed explanation, very interesting! I got your point concerning |
Some more thoughts on this... The general guiding principle I've used in variadic tuple type inference is to not make speculative inferences. For example, don't attempt to infer to With that in mind, I'm now thinking that we shouldn't even attempt to infer to function foo<T extends unknown[]>(a: [...T], b: [...T, number?]): T;
foo([1, 2], [1, 2, 3]); // Should infer [1, 2]
foo([1, 2, 3], [1, 2, 3]); // Should infer [1, 2, 3] We'd need to give higher priority to inferences from the first argument because they're not speculative. Generally, I'd prefer avoiding speculative inferences, so I think the resolution to this issue is to simply make no inferences to |
With #39281 we no longer make speculative inferences to variadic tuple types. declare function foo1<T extends string[]>(t: [...T, number?]): T;
const v11 = foo1([]); // string[]
const v12 = foo1(["bar"]); // string[]
const v13 = foo1(["bar", 42]); // string[]
declare function foo2<T extends string[] = []>(t: [...T, number?]): T;
const v21 = foo2([]); // []
const v22 = foo2(["bar"]); // [] and error
const v23 = foo2(["bar", 42]); // [] and error Use overloads to get the desired effect of an optional ending declare function foo3<T extends string[] = []>(t: [...T, number]): T;
declare function foo3<T extends string[] = []>(t: [...T]): T;
const v31 = foo3([]); // []
const v32 = foo3(["bar"]); // ["bar]
const v33 = foo3(["bar", 42]); // ["bar"]
const v34 = foo3(["bar", "baz"]); // ["bar", "baz"] |
Sounds like a reasonable compromise between practicability and consistency. Given following example:
If I have understood correctly, same as above holds true: the compiler cannot infer |
That's correct, when we make no inferences for a particular type parameter, we default to the constraint. Then tuple type normalization turns |
TypeScript Version: 4.0.0-dev.20200624 (Nightly)
Search Terms: variadic tuple optional element type inference
Code
Expected behavior:
The inferred types via
foo
helper function (v21
etc.) are the same as explicitly annotated types (v11
etc.).I would expect the passed in array literal value in
foo
to be narrowed to a tuple type, as explained in the PR:Actual behavior:
Either the resulting type is an array (
v21
) or does not take the variadic type into account (v22
), despite explicit[...T, number?]
return type forfoo
. Alsov22
errors now.I could live with
v21
, but shouldn't it be clear to the compiler inv22
, that the resulting type is akin to["bar", undefined?]
?Playground Link:
here
Related Issues:
The text was updated successfully, but these errors were encountered: