-
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
Generic not inferred from contextual types #25293
Comments
hmm I don't think this is valid. What you are after is following: // inferred bar 👉 (x: number) => number
const bar = identity((x: number) => x) by doing const bar: (n: number) => number = identity(
x => x
); you're telling compiler that |
I thought TypeScript would use |
I might be wrong but I don't think so, that would mean that Generics can flow deeply to function calls. but again explicitly annotating a variable is expressing what type should be on the right side of assignment, not to infer |
This is working as intended. Function and arrow expression parameters without type annotations are assigned contextual types only when the contextual type is known (before instantiation) to be a function type. In your example the contextual type is simply |
yup what @ahejlsberg and (myself partially) said :) |
Thanks for the explanation @ahejlsberg and @Hotell. To justify why I would like this with a real world use case: const numberPromise = Promise.resolve(1);
numberPromise.then(
// x is inferred as number, no type annotation required
x => x + 1
);
// Later, when I need to expand on this function, if I use `pipe` I'm
// forced to add a type annotation to the parameter when it wasn't
// needed before.
numberPromise.then(pipe(
// x is inferred as any, requiring me to add a type
// annotation to the param that wasn't needed before
x => x + 1,
x => x * 2,
));
numberPromise.then(pipe(
(x: number) => x + 1,
x => x * 2,
)); |
@OliverJAsh How is |
@ahejlsberg I'm using |
Hmm interesting, those definitions might be wrong ? this works declare const pipe: <A, R1, R2>(a: (arg: A) => R1, b: (args: R1) => R2) => (resolved: A) => R2
// $Expect Promise<number>
const numberPromise = Promise.resolve(1)
numberPromise.then(
// $Expect (x:number)=>number
(x) => x + 1
)
// $Expect Promise<number>
const result = numberPromise.then(
pipe(
// $Expect (x:number)=>number
(x) => x + 1,
// $Expect (x:number)=>number
(x) => x * 2
)
) |
The issue appears to be that the |
Ahh, that's good to know, so we can at least workaround it by patching the I realised my original example was off the mark. Here is a correct example which does show the actual problem, as you described: // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/64104e9760065bd498a3d62d98bb05ea26500dc2/types/lodash/common/util.d.ts#L209
declare const pipe: {
// 0-argument first function
<R1, R2>(f1: () => R1, f2: (a: R1) => R2): () => R2;
// 1-argument first function
<A1, R1, R2>(f1: (a1: A1) => R1, f2: (a: R1) => R2): (a1: A1) => R2;
}
const bar: (n: number) => number = pipe(
// param `n` is inferred as `any`, expected `number` :-(
x => x + 1,
x => x * 2
); If you remove the first overload, the param |
I guess this can be labelled as "won't fix"? |
TypeScript Version: 2.9.2
Search Terms: generic infer contextual type
Code
Expected behavior: TypeScript should infer the generic
T
inidentity
from the contextual type.Actual behavior: TypeScript infers the generic
T
inidentity
asany
!Playground Link:
Related Issues:
The text was updated successfully, but these errors were encountered: