-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Type inference for piped arrow functions #22081
Comments
I really think this is the old problem about having 2 inference sites for the same type variable. Let me try to find the issue. Here you go: #14829 Here is your code with the fix suggested in that issue: export type NoInfer<T> = T & {[K in keyof T]: T[K]};
const pipe = <A, B, C>(
x: A,
a: (x: A) => B,
b: (x: NoInfer<B>) => C,
) => b(a(x));
const call = <A, B>(f: (x: A) => B) => (x: A) => f(x)
const a = pipe(1, x => x + 1, call(x => x + 1));
const b = pipe(1, call(x => x + 1), call(x => x + 1)); |
@sylvanaar Interesting, thanks! Unfortunately that fix doesn't seem to work with strictFunctionTypes. Another thing is it seems to me that the NoInfer feature is intended for cases when TypeScript can successfully infer the type on both of the sites, and you want to tell it to prefer one site over another, but not for the cases when it can infer the type on one site but can't infer it on the other site. If it helps, this is what I think of as a typical use case for NoInfer: const defaultValue = <T>(source: T | undefined, defaultValue: NoInfer<T>) =>
source === undefined ? defaultValue : source;
type A = { a?: number };
// Typescript can infer the type from the second argument, but you don't
// want it to do it because then .a would be causing an error.
const f = (arg: A | undefined) => defaultValue(arg, {}).a; |
Just trying to explain to you what is happening. Inference is occurring at the site with the unbound type variables, so you end up inferring {} for B. This only happens if you mix supplying functions with unbound type variables and functions without them as arguments for some reason.
It seems like the type substitution is happening in multiple phases, and seems to prefer inferring the type from what you passed to call instead of treating what you passed as a function with unbound type parameters. Anyways - let's see what MS has to say. |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
@mhegazy Not sure if it's a good idea to close this issue — right now when you're using pipes, you often have to use a counterintuitive |
Any news on this? I just updated from angular 5 to 6, which entails rxjs v6+ and I have this issue all over my project. Surprised there aren't more complaints out there seeing how popular angular is. |
This is quite annoying and should not be closed. |
My understanding is that @mhegazy is "moving on to new adventures". Should this be closed, @RyanCavanaugh ? |
This is a limitation of the current inference algorithm. We don't have a good way to know that inference in this function is supposed to proceed left-to-right and that the inference needs to happen in two discrete steps (first resolving |
See also #25826 |
TypeScript Version: 2.7.1 (the issue occurs independently of whether the strict mode, including strictFunctionTypes, is turned on)
Search Terms: pipe, type inference, generic
Code/actual behavior:
Expected behavior:
Typescript should be able to infer the types for the simpler one of the these two lines if it can infer them for the more complex one.
Playground Link:
Playground
Related Issues:
This issue originates from discussion here #22051.
The text was updated successfully, but these errors were encountered: