Skip to content
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

Failure to infer parameter type #25444

Closed
pelotom opened this issue Jul 5, 2018 · 5 comments
Closed

Failure to infer parameter type #25444

pelotom opened this issue Jul 5, 2018 · 5 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@pelotom
Copy link

pelotom commented Jul 5, 2018

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'.

Playground Link

@pelotom pelotom changed the title Conditional type inference failure Parameter inference failure with conditional types Jul 5, 2018
@pelotom pelotom changed the title Parameter inference failure with conditional types Failure to infer parameter type Jul 5, 2018
@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jul 19, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Jul 19, 2018

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) { },
});

@pelotom
Copy link
Author

pelotom commented Jul 19, 2018

@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?

@mhegazy
Copy link
Contributor

mhegazy commented Jul 19, 2018

Conditional types do not contribute to inferences.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@pelotom
Copy link
Author

pelotom commented Aug 14, 2018

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants