Skip to content

Generic inference of Overloaded methods only working with the last defined methodΒ #43187

Open

Description

Bug Report

πŸ”Ž Search Terms

  • Generics
  • Overload
  • Type inference

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about overloading

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

class SomeClazz {
    public overload(param: 'PARAM1'): number;
    public overload(param: 'PARAM2'): string;

    public overload(param: 'PARAM1' | 'PARAM2'): number | string {
        switch (param) {
            case 'PARAM1':
                return 1337;
            case 'PARAM2':
                return 'Hi';
        }
    }
}

function call<Ctx extends { [F in Name]: (this: Context, ...args: any[]) => any }, Name extends string>(
    ctx: Ctx,
    method: Name,
    ...args: Parameters<Ctx[Name]>
): void {
    ctx[method](...args);
}

const clazz = new SomeClazz();
clazz.overload('PARAM1'); // Works ok
clazz.overload('PARAM2'); // works ok
call(clazz, 'overload', 'PARAM1'); // ERROR: Argument of type '"PARAM1"' is not assignable to parameter of type '"PARAM2"'
call(clazz, 'overload', 'PARAM2'); // Works ok

Workbench Repro

πŸ™ Actual behavior

  • Only one function overload is taken into account when inferring function parameter types

πŸ™‚ Expected behavior

  • All function overloads should be taken into account when inferring function parameter types

Activity

  1. MartinJohns commented on Mar 11, 2021

    @MartinJohns
    Contributor

    Type inference in conditional types, such as Parameters<T>, does not work with overloads. In this case the last signature is used, as you noticed. This is a design limitation and is mentioned in the docs.

    edit:

    My bad. The documentation that mentioned this behavior (Advanced Types) has officially been deprecated, and the new documentation does not mention this limitation at all (I've created a PR).

    When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.

  2. jcalz commented on Nov 17, 2021

    @jcalz
    Contributor

    Note that there are no conditional types in this example; the particular limitation here is for generic type parameter inference, (which has the same problem of course).

  3. rpeszek commented on Apr 9, 2022

    @rpeszek

    It should be noted that this could cause the code to be brittle. Changing ordering of overloads is likely to result in compilation breaking.

    This is likely to happen with office.js which has a quite complex overloaded design.

    I have implemented an example inspired by office.js here:

    https://github.com/rpeszek/typescript-issues/blob/master/src/RejectingCorrectCode/RejectingOverloads.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocsThe issue relates to how you learn TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions