Multiple function or method declarations describe overloads. Overloaded functions or methods have one or more call signatures which are part of the declaration of the type. You can represent this set of call signatures either as repeated function/method/callable signatures in an interface/class/scope, or as the intersection of all the call signatures. An overloaded function must be callable in each of the ways described by the call signatures.
When you implement an overloaded function or method, you use a single implementation signature which is not seen from the outside... it's an implementation detail of the function. But the implementation signature needs to be able to handle all the call signatures. If it can't, you have a problem.
I'll rewrite your code as a single overloaded function interface MyMethod:
interface MyMethod {
(num: number): number; // declaration 1
(str: string, num: number): number; // declaration 2
}
let func1: MyMethod = (num: number) => 0; // error
let func2: MyMethod = (str: string, num: number) => 0; // error
That's basically the same as your code, and it has the same problem. func1 is not a valid MyMethod. You can only call func1(123), but you can't call func1("abc",123). But a MyMethod has to support both calls. Similarly, func2 only supports the second call signature and not the first.
Now consider this:
let funcBoth: MyMethod = (strOrNum: string | number, num?: number) => 0; // okay
This compiles just fine. That's because the implementation signature of funcBoth can support being called like funcBoth(123) and like funcBoth("abc", 123):
funcBoth(123); // okay
funcBoth("abc", 123); // okay
Now, the implementation signature would also have supported being called like funcBoth(123, 456), but the annotation of funcBoth as MyMethod does not let you do that:
funcBoth(123, 456); // error! bad first argument
So the implementation signature is hidden from callers, and so inside your function implementation you can safely rely on the fact that callers will not pass in unexpected parameters.
If you want the behavior of calling func1 or func2 depending on how funcBoth is called, you have to do the dispatching yourself by checking arguments:
let f1 = (num: number) => 0;
let f2 = (str: string, num: number) => 0;
let f12: MyMethod = (strOrNum: string | number, num?: number) =>
typeof strOrNum === "number" ? f1(strOrNum) : f2(strOrNum, num!);
Okay, hope that helps; good luck!
Link to code