Overload method with spread operator not recognized

Viewed 287

I have a class definition as follows:

class Test {
  a(msg: string): string;
  a(msg: string, ...args: unknown[]): string | { msg: string, args: unknown[]} {
    if (args) {
      return { msg: msg, args: args };
    }
    return msg;
  }
}

However, I get compilation errors if I do this:

new Test().a("test", "a", 1, 2, 3);

"Expected 1 arguments, but got 5"

How can I properly overload this method to provide different return types for the different signatures?

2 Answers

The function implementation is not part of all available overloads. Instead you can write:

class Test {
    a(msg: string): string; // overload 1
    a(msg: string, ...args: unknown[]): { msg: string, args: unknown[] } // overload2
    a(msg: string, ...args: unknown[]): string | { msg: string, args: unknown[] } { // impl
       // ...
    }
}
new Test().a("test", "a", 1, 2, 3); // { msg: string; args: unknown[]; }
new Test().a("test") // string

Playground sample

Typescript does not support function overloading with different number of parameters.

Documentation says:

TypeScript provides the concept of function overloading. You can have multiple functions with the same name but different parameter types and return type. However, the number of parameters should be the same.
[...] Function overloading with different number of parameters and types with same name is not supported.

One trick to achieve what you are trying could be this

interface ReturnA {
    msg: string;
    args: any[];
}

class Test {

  a(msg: string, ...args: never[]): string;
  a(msg: string, ...args: any[]): ReturnA
  a(msg: string, ...args: any[]): string | ReturnA {
    if (args) return { msg, args };
    return msg;
  }

}

const t = new Test();

// only 1 param returns string
const str: string = t.a(`a`); 

// two or more params returns the other object type
const obj: ReturnA = t.a(`a`, `param1`); 
Related