TypeScript Version: 3.0.0-dev.20180704
Search Terms: parameter inference
For context, I'm trying to provide accurate typings for a JS library (Material UI). What follows is an extreme simplification of the problem, dealing with functions rather than components:
Code
const foo = <A>(f: (x: A) => void, x: A) => f(x);
foo(
(x: (n: number) => void) => x(42),
n => console.log(n)
);
Expected behavior:
Should infer the type of the n parameter of the second argument as number.
Actual behavior:
Infers n: any, which rightly fails when noImplicitAny is enabled. However the compiler clearly knows what the type of the n parameter should be... if it's annotated incorrectly, e.g.
(n: string) => console.log(n)
then we get an error saying
Argument of type '(x: (n: number) => void) => void' is not assignable to parameter of type '(x: (n: string) => void) => void'.
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'n' and 'n' are incompatible.
Type 'number' is not assignable to type 'string'.
What is happening here is to infere the type of P, the compiler needs to know the type of bar and to know that it needs an inference for P, which at this point is not available.
You can explicitly specify the type argument to the call:
foo<{ bar(x: number): void }>({
f(p) { },
bar(x) { },
});
@mhegazy can you look at my revised example? What surprises me is that not even this works:
const foo = <F extends (x: any) => any>(f: F, x: F extends (x: infer A) => any ? A : never) => f(x);
foo(
(x: (n: number) => void) => x(42),
n => console.log(n)
);
Here the type of x should be completely contingent on the type of f, and not at all the other way around, right? Where is the circularity here?
Conditional types do not contribute to inferences.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
I'd like to petition to get this reopened. It would vastly simplify the typing of a major library (Material UI) if we could get TypeScript to infer a reasonable least upper bound instead of any. It clearly knows what that LUB should be, because if you put anything else, it will give a type error. Please reconsider closing this!
Most helpful comment
I'd like to petition to get this reopened. It would vastly simplify the typing of a major library (Material UI) if we could get TypeScript to infer a reasonable least upper bound instead of
any. It clearly knows what that LUB should be, because if you put anything else, it will give a type error. Please reconsider closing this!