-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
Function argument types only inferred for mapped function with the maximum number of arguments #17391
Comments
This does seem buggy to me. What's a minimal example of it? interface Functions {
's': (s: string) => void;
'ns': (n: number, s: string) => void;
}
declare function getFunction<K extends keyof Functions>(key: K, func: Functions[K]): void;
getFunction('ns', (x, y) => { x.random; y.random }); // good errors, x is number, y is string
getFunction('s', (x) => { x.random }); // bad, x has any type?!
getFunction('s', (x: number) => { }); // good error, string is not assignable to number
getFunction('s', (x: string) => { }); // workaround, no error
getFunction('s', (x => {}) as Functions['s']); // workaround, no error It's strange to me that the compiler does infer the right function type but does not infer the parameter types for that function. Obviously you can work around it by specifying the type on the parameter(s), but it seems eminently inferable to me. Is this a bug or a weird limitation? |
This is still an issue in version 3.2.0-dev.20180927 Repro: interface FnMap {
a: (x: string) => any;
b: (x: number) => any;
}
declare function on<K extends keyof FnMap>(key: K, fn: FnMap[K]): void;
on('a', x => console.log(x)); // Bad: x is not inferred
on('b', x => console.log(x)); // Bad: x is not inferred
declare function handle_it(x: string): void;
on('a', handle_it); // Good
on('b', handle_it); // Good - Error It looks like the actual type mapping is fine, since using the explicitly typed function produces the expected results, so the problem is with the type inference of the arguments of the anonymous functions. |
@yseymour Nice! Here's a slight variation on your example that I think provides some additional insight: interface FnMap {
a: (x: string) => any;
b: (x: number, y: number) => any;
}
declare function on<K extends keyof FnMap>(key: K, fn: FnMap[K]): void;
on('a', x => console.log(x)); // Bad: x is not inferred
on('b', (x, y) => console.log(x, y)); // Good: x and y are inferred I think the core of the problem might be that the callback provided for |
This works now |
TypeScript Version: 2.4.1
Code
Expected behavior:
Types are inferred for all event callback arguments.
Actual behavior:
Types are inferred only for the callback arguments of the event
'four'
. If'four'
is removed fromMyEvents
, then only the callback arguments for'three'
are inferred. If'three'
is removed, then only the arguments for'two'
are inferred. etc.The order of properties on
MyEvents
has no effect, and if there are multiple events with the maximum number of arguments they are all inferred correctly.EDIT: I just noticed adding another function with the same number of arguments, but different types also prevents arguments from being inferred, so this is probably an issue with merging the type signatures. Interestingly IntelliSense (both in VSCode, and the online playground) can still infer the proper types.
The text was updated successfully, but these errors were encountered: