-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Suggest specifying generic as union if candidates are different #20339
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
Elm provides some inspiration here. Taking the same examples: compare : a -> a -> a
compare a b = a
result = compare 1 "foo"
match : { foo: a, bar: a } -> a
match cases = cases.foo
result = match { foo = 1, bar = "foo" }
|
We've been chatting internally about how to make this experience better from the type system side. There are some functions (e.g. VB's After reviewing all the functions in that linked issue, I'm increasingly convinced that the correctness of a union inference is an intrinsic property of the function itself, rather than a call-site decision. If the provided call to |
Regarding the error message.. this happens in an earlier phase before overload resolution, and the compiler does not have the full information about which parameter is used here, all it knows is that it made two inferences that are not compatible for a type parameter. we are open to ideas to make the error message better if you want to take a stab at it. |
Is this enough information for us to provide an explicit warning to the user that the two type parameter inferences are incompatible? Currently, TypeScript just tells us the argument is not assignable to the expected parameter type, but it doesn't say why (because the second inference is different from the first?). If I understand the situation correctly, I will attempt a proposal. |
Some historical context, the behavior has changed in TS 2.4, and we have tried both.. so consider: declare function add<T>(list: T[], newItem: T): void;
add([1, 2], "string"); TS 2.4 and later
Before TS 2.4
Users have found the old error less helpful. we switched to pick the first candidate in cases inference ends up with multiple irreducible candidates to make the error closer to the arguments (like you mentioned with Elm), the idea is that would help you fix it better than telling you My comment earlier was if we stop doing what we are doing today, and instead go back to the old behavior where all we know is that I think the current error is better, but we are always open to suggestions to make the experience better. as a matter of fact, that change in TS 2.4 was a user suggestion as well (can not seem to find the link though). |
Very interesting, thank you for that explanation. I actually think both of those error messages are useful. The current error message tells me what the exact type issue is, and the former error message gives me some information as to the cause. Perhaps we could combine the two somehow? Out of interest, what would be the equivalent pre TS 2.4 error for the |
a.ts(5,5): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
Type argument candidate '"oops"' is not a valid type argument because it is not a supertype of candidate '42'.
a.ts(21,5): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate 'string'. |
Continuing with the examples above, does something like this work? (Probably not, I'm most definitely missing edge cases.)
|
the issue is not the error text, it is how the error would be produced in the compiler. the two processes, inference, and overload resolution are rather detached.. |
What if In that case it's not possible to provide a generic for each parameter, since the number of parameters is dynamic. |
TypeScript Version: 2.6.1.
Code
– https://stackoverflow.com/questions/39905523/why-isnt-the-type-argument-inferred-as-a-union-type/39905723#39905723
This makes sense, however I would like to question whether we can improve the user experience around this, so errors due to this constraint are easier to understand and fix.
For example:
As a TypeScript user, I have struggled with these errors many times, and I've only recently realised the specific constraint on the type system which is the root cause of these errors: generics are picked from the first candidate and are not widened to include all candidates. I have also seen other people struggle with this when learning TypeScript.
We can fix this error by specifying the generic as a union:
However, this fix is really not obvious from the error message, especially if the user is not aware of this constraint on the type system (that generics will not be inferred as unions).
I'm wondering if there's any way we can better surface this constraint to the user, to make it clearer to users how they can fix these type errors, such as by specifying the generic as a union (if that is what they intend).
The text was updated successfully, but these errors were encountered: