Function Overloading / Method Overloading TypeScript

Function overloading (or Method Overloading) is a feature where two or more functions can have the same name but with different parameters and implementations. The function overloading is not available in JavaScript. But Typescript does allow us to create several overload signatures of a function. We can use those overload signatures to call the function and thus mimicking the function overloading. Let us learn how to create an overloaded function in TypeScript using examples

What is Function Overloading?

Take a look at the following two Add functions. We either pass two numbers or an array of numbers. it will add the numbers are return the sum.

This add function accepts two numbers and returns their sum.

This add function accepts an array of numbers. It calculates their sum and returns it.

But, we cannot use both the functions either in JavaScript or in TypeScript.

JavaScript does allow us to create multiple functions with the same name. But it overrides the previously written function. It always calls the last declared function irrespective of how many functions you have declared.

While Typescript does not allow us to same name for multiple functions. It throws a Duplicate function implementation error if we try to do so.

The languages like C#, Java, etc. allows us to create functions with the same name, but with different parameters and return types. It is known as function overloading.

The ability to use two or more functions with the same name brings consistency in the naming of functions. It also makes it easier to remember the function names. For example, add function always adds the numbers or joins the strings. A print method will print whatever you pass into it.

But in JavaScript where we do not have overloading, we have two options.

One is to create separate functions for each variation in arguments like addNum, addNumArray etc. In this case, we need to check the data type of the arguments and call the correct function.

The second option is to create a single function and check the data type of the arguments passed and call the appropriate code within that function. This is the preferred way in JavaScript.

Creating overloaded functions in TypeScript

Since Typescript is based on JavaScript, it does not allow us to create Overloaded functions with the same name. Instead, it allows us to create overload signatures for a regular function.

To create function overloading first, we need to create a regular function. This function must check the type of the arguments passed to it and call the appropriate code within that function. We call this an implementation function.

Next, we create overload signatures for that function and use those signatures to call the function.

Let us learn how to do it using the add function from the previous section

Overload Signatures

Overload signature defines how we intend to call the function. It contains only the signatures and does not contain any code. It is basically a function declaration without any code.

We would like to call our add function in two ways. One is to pass two numbers and the other way is to pass an array of numbers.

Hence create a function declaration statement for the above, without the function body. This is our overload signatures.

Implementation Function

The implementation function is a function that actually contains the code. Its signature must be generic enough to cover all the overloads.

Since our add function takes 2 arguments at most, our implementation function must also accept two arguments. We make the second argument optional because the first overload signature takes only one argument.

The first argument is number in the first Overload signature and number[] array in the second overload signature. Hence the first argument in the implementation function is a union type of number|number[].

Similarly, the second argument is the add function is of type number.

Inside the function, we check if the arg1 is an array and if yes we add the numbers. If the arg1 is not an array, then we make checks to see if arg1 & arg2 are numbers and add them and return the result back.

Finally, we place the overload signatures directly above the implementation function.

Now, you can call the function using the overload signatures.

Trying to call the function with any other way will result in a compiler error

The number of Arguments

The overload signatures can have any number of arguments. But the number of arguments in the implementation function must be equal (or greater) to the overload signature with the most number of arguments.

In this example, one of the overload signatures has three arguments and the other one has one. Hence the implementation function must have at least three arguments.

Optional Arguments

We need to mark some arguments as optional if any of the overload signatures do not have the same number of arguments as in the implementation function.

In this example, the first overload signature has only one argument. Hence in the implementation function, any argument above one must be marked as optional.

If we do not mark the argument as optional, then the first overload signature which has only one argument will not be compatible with the implementation function which has three arguments. It will result in “This overload signature is not compatible with its implementation signature” error.

The arguments data type must be compatible

The data type arguments in the implementation function must be compatible with the data type in the overload signature.

In this example, the data type of the first argument in overload signature is string and number. Hence the first argument in the implementation function must be a type that is compatible with both string and number. That gives us three options. A union type of string|number, any type & unknown type.

Using an incompatible type will result in “This overload signature is not compatible with its implementation signature” compiler error.

The implementation function should be the last

The overload signatures must be placed directly above the implementation function. The following code is invalid, because of the let statement placed between the overload signature and the implementation function. Typescript compiler throws the “Function implementation is missing or not immediately following the declaration” error

This also causes errors because the implementation function comes first before the overload function.

Return types can be different

The return type of the overload signatures can be different. In this example return type either a string or a number. Hence the implementation function returns the compatible type string|number. You can also use any or unknown.

Implementation Signature is not callable

This code does not throw any compiler error, because we are using any type in the function argument

But adding an overload signature will result in “No overload matches this call” error. This is because once a function has an overload signature declared, you cannot use the implementation function signature to call the function.

Order of overload signature in Important

Order of overload signature is important. TypeScript chooses the first matching overload when resolving function calls. Hence we need to put the more specific signatures before the more general signatures

The following example has two overload signatures. The first one takes the unknown as an argument and returns the unknown. The second signature takes a number array and returns a number.

We call the function with a number array, which is our second overload signature. Hence we expect it to return a number. But hovering over the return variable you will see that it is inferred as unknown.

This is because the unknown is a more general type than a number. The number array can be assigned to an unknown and not the other way around. Hence the typescript compiler thinks we are using the first overload signature.

Moving the second overload to the first does solve the problem.

Method overloading

A function that is part of a class is known as Method. You can create overload signatures in the class just like we did for the standalone functions.

This example shows the add function implemented as a method in the calculator class.

References

  1. Function Overloading Do & Donts
  2. Overloaded Functions

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top