-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Cannot infer generic argument type from passed callback #31146
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
Another thing I noticed is that this works for functions declared on the same scope but fails for function expressions passed in to the HOF const inferArguments = <T>(callback: T) => callback;
function noop(){}
function takesNoop({ a = noop}) {}
const OK = inferArguments(takesNoop);
OK({a: noop}); // OK!
OK({b: noop}); // Expected error - Got one!
OK({a: false}); // Expected error - Got one!
const BAD = inferArguments(function takesNoop({ a = noop}) {});
BAD({a: noop}); // OK!
BAD({b: noop}); // Expected error - No Error!
BAD({a: false}); // Expected error - No Error! |
Set |
I have a maybe related issue: function f(a) { // Would emit an error with noImplicitAny
return () => a
}
const x = f(1) // I would have expected `x` to be `() => number`, but it is `() => any`
const y: string = x() // Passes function f<T>(a: T) {
return () => a
}
const x = f(1) // `() => number`
const y: string = x() // Fails |
Looks like a bug to me - the default in the binding pattern should have made a candidate for |
Any update on this? I'm running into an issue that is perhaps related. In the following function,
Happy to provide more details and/or help debug if it makes sense. |
I've also run into this same issue. It would be nice to see it fixed. |
A common issue is having to manually specify a type for the Promise constructor. (tested in Visual Studio Code with TypeScript 3.7.2) const p = new Promise((resolve) => resolve(1))
const p = new Promise<number>((resolve) => resolve(1)) @pradyuman I've also run into the same issue with making my own wrapper for gRPC calls. I found that it is due to having multiple overloads for Here's a reproducible example (tested in Visual Studio Code with TypeScript 3.7.2), using number instead of gRPC request/response protobuf types: function f<T, U> (
call: (
request: U,
innerCallback: (error: Error | null, value?: T) => void
) => void,
request: U): Promise<T> {
return new Promise((resolve, reject) => call(request, (error, response) => {
if (error) {
reject(error)
} else {
resolve(response)
}
}))
}
declare function p (request: number, call: (error: null, a: number) => void)
// declare function p (request: number, a2: boolean, call: (error: null, a: number) => void)
async function g () {
const v = await f(p, 1)
// the type of v is inferred as number
// but if the other declaration above is uncommented, it is inferred as unknown
} My workaround is to specify the type explicitly ( |
@RyanCavanaugh this affects event react typings for typescript: Because now any usage useCallback leads to silent any inference Any update on this? |
C# can't infer the types either: using System;
namespace ConsoleApp1
{
static class Program
{
static void f<T>(Action<Action<T>> c)
{
c(x => Console.WriteLine(x));
}
static void Main(string[] a)
{
f(x => x("test")); // error
}
}
} Java can though: import java.util.function.Consumer;
public class Main {
static <T> T f(Consumer<Consumer<T>> c) {
c.accept(x -> System.out.println(x));
return null;
}
public static void main(String[] args) {
String s = f(x -> x.accept("a")); // output: a
String s2 = f(Main::g); // output: a
// Integer i = f(x -> x.accept("a")); // does not compile, good
}
static void g(Consumer<String> c) { c.accept("a"); }
} |
Ran into the same issue today! Any plans to get it fixed? |
That's because react typings don't provide typings for >TS 3.0. For example, we use the following
|
In TypeScript, this is the current issue (affecting type Action<T> = (t: T) => void
// the original example in the original post seems to be OK now, as there is an error for
// const implicit = inferArguments(({a = noop}) => {});
function f<T>(_: Action<T>): T { return null as any; }
const x = f((_: string) => {}); // y has type string, OK
// current issue in TypeScript 3.7 to 4.0
function f2<T>(_: Action<Action<T>>): T { return null as any; }
const y = f2(x => x("1")); // y has type unknown, BAD <------------------------------
const y2 = f2((x: Action<string>) => x("1")); // y2 has type string, OK
const y3 = f2<string>(x => x("1")); // y3 has type string, OK Also, it actually turns out that C# can infer the type when it is explicitly written and not a method group: using System;
void f<T>(Action<Action<T>> c) { }
void g(Action<string> f) { }
f((Action<string> f) => f("a")); // ok
// f(f => f("a")); // error
// f(g); // error
void f2<T>(Action<T> c) { }
void g2(string s) { }
f2((string _) => {}); // ok
// f2(g2); // error |
TypeScript Version: 3.4.0-dev.201xxxxx
Search Terms:
infer, parameter, argument, callback, function
Code
Expected behavior:
Both function calls with
({a: false})
should cause a type errorActual behavior:
Only the function call with the explicit typing causes a type error
Playground Link
Related Issues: #30975 Looks similar but seems different since there should be a clear way for inference to work in this case
Note that
Parameters
is correctly able to extract the correct types for such a construct as seen in this bit of code:This appears to be an error with inline callback functions used in this fashion
The text was updated successfully, but these errors were encountered: