Skip to content

Inference failing for conditional types in function parameters #33369

Closed as not planned
@squidfunk

Description

@squidfunk

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

export interface Foo<T> {
  bar: T
}

export type FooType<T> = T extends Foo<infer U> ? U : never
export type FooLike<T> = T extends Foo<FooType<T>> ? T : never

export type FooQueryType<T> =
  T extends (foo: infer U, ...args: any[]) => boolean
    ? U extends FooLike<infer V>
      ? V
      : never
    : never

export type FooQueryParameters<T> =
  T extends (foo: any, ...args: infer U) => boolean
    ? U
    : never

export type FooQueryLike<T> =
  T extends (foo: FooQueryType<T>, ...args: any[]) => boolean
    ? T
    : never

export type FooQuery<T> = (foo: FooLike<T>) => boolean

export function matchWithBrokenInference<T>(
  fn: FooQueryLike<T>, ...args: FooQueryParameters<T>
): FooQuery<FooQueryType<T>> {
  return foo => fn(foo, ...args)
}

export function matchWithCorrectInference<T, U extends FooQueryLike<T>>(
  fn: T, ...args: FooQueryParameters<U>
): FooQuery<FooQueryType<U>> {
  return foo => (fn as U)(foo, ...args)
}

function query<T extends Foo<string>>(foo: FooLike<T>, data: string) {
  return true
}

const q1 = matchWithBrokenInference(query, "test") // incorrect inference of query
const q2 = matchWithCorrectInference(query, "test")

Expected behavior:

matchWithBrokenInference infers query correctly.

Actual behavior:

matchWithBrokenInference infers query incorrectly.

Playground Link: reproducible example

Related Issues: None found

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions