Function overloading in TypeScript is a little enigmatic and complicated to learn at first. It doesn't work like traditional overloading in other languages like C# or Java where you just create a new function with the same name but different parameters. Function overloading in TypeScript is more like defining facades for a function.
An example would make it easier to see how this works. Say we want to have a getter and setter methods with the same name. First let's just write it as one function without any overloads.
If a string parameter is passed in it will set the backing variable and return nothing. If no parameter is passed it will return the value of the backing variable. This will work, but the function signature isn't very intuitive or user friendly. So let's add some overloads, or facades, that will make it more apparent how to use it.
We've added two signature overloads. Notice that the overload signatures must come before the actual function body. The first is our getter which takes no parameters and returns a string. The second is our setter which takes a string parameter and has a return type of void. Both of these signatures must be compatible with the real function definition's signature.
Let's look at another example. This time we'll make a class called Color and overload the constructor so that you can either pass in a string color identifier or red, green and blue components.
Notice that the first parameter rOrDef is defined as "any" so that it can take a string or number. The g and b parameters are marked as optional. Then we can simply create our two signature facades, one that takes one string parameter, and another that takes three number parameters.
Once you realize that there is no such thing as function overloading in TypeScript that's the key to understanding it. You're actually creating facades that make it easier for someone to call a function that will accept many different types of parameters.