-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Inference failing for conditional types in function parameters #33369
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
This type, type FooQueryLike<T> =
T extends (foo: FooQueryType<T>, ...args: any[]) => boolean
? T
: never And your usage of it are very suspicious. I've also noticed you don't constrain your type parameters and choose to leave them implicitly unknown. You should constrain them as much as possible. For example, this, export type FooType<T> = T extends Foo<infer U> ? U : never Can be rewritten as, export type FooType<T extends Foo<any>> = T["bar"] Saving you the need to use a conditional type. Conditional types should really be more of a last resort. I'm on mobile now so I can't poke at it more. Upon a little more inspection, your types can be greatly simplified but I'm not going to do that on my phone =x |
Okay, I tried to simplify on mobile, lol, export interface Foo<T=any> {
bar: T
}
type Query = (foo: Foo, ...args: any[]) => boolean;
export type QueryFoo<T extends Query> =
T extends (foo: infer U, ...args: any[]) => boolean ?
U :
never
export type QueryParameters<T extends Query> =
T extends (foo: any, ...args: infer U) => boolean
? U
: never
export type Result<T extends Foo> = (foo: T) => boolean
declare function match<T extends Query> (query : T, ...args : QueryParameters<T>) : (
Result<QueryFoo<T>>
); [Edit] |
I'm even tempted to say this should work, export interface Foo<T=any> {
bar: T
}
export type Result<FooT extends Foo> = (foo: FooT) => boolean
declare function match<
FooT extends Foo,
ParamsT extends readonly any[]
> (
query : (foo : FooT, ...args : ParamsT) => boolean,
...args : ParamsT
) : (
Result<FooT>
); However, I'm on mobile and can't test that |
@AnyhowStep thanks for your input on this. I agree with you in general, but actually, the |
I just tested and the type of export interface Foo<T=any> {
bar: T
}
export type Result<FooT extends Foo> = (foo: FooT) => boolean
declare function match<
FooT extends Foo,
ParamsT extends readonly any[]
> (
query : (foo : FooT, ...args : ParamsT) => boolean,
...args : ParamsT
) : (
Result<FooT>
);
interface MyFooLike {
bar : "haha",
baz : "hehe",
}
declare function myQuery (
foo : MyFooLike,
arg0 : number,
arg1 : Date
) : boolean;
//const result: Result<MyFooLike>
const result = match(myQuery, 3.141, new Date());
//type resultParams = [MyFooLike]
type resultParams = Parameters<typeof result>; You can see
|
OK, so the issue is due to contextual typing; specifically recent additions around generic signatures. The contextual type of |
Additionally, even if we got past that, when we go to compare |
Based on the above explanation, I'm going to track this as a duplicate of #26933 |
When using generics with conditionals in a function's signature, type inference seems to break down. I narrowed the problem down to the following reproducible case. Interestingly, the issues vanishes when another generic "helper" parameter is introduced, as can be seen in the example.
TypeScript Version: 3.6.3, 3.6.2, 3.5.x
Search Terms: parameter, inference, functions, generic, conditional types
Code
Expected behavior:
matchWithBrokenInference
infersquery
correctly.Actual behavior:
matchWithBrokenInference
infersquery
incorrectly.Playground Link: reproducible example
Related Issues: None found
The text was updated successfully, but these errors were encountered: