Table of contents
1.
Introduction
2.
Function Overloads
2.1.
Advantage of function overloading
3.
Function overloading in a class
4.
When to use function overloading?
5.
Do’s and Don’t 
5.1.
Ordering
5.2.
Optional Parameter
5.3.
Union Type
6.
FAQs
7.
Key Takeaways
Last Updated: Mar 27, 2024

Function Overloading in TypeScript

Author Aryan Raj
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

TypeScript is a language for application-scale JavaScript. Typescript adds optional types to JS that support tools for large-scale JavaScript applications for any browser, host, or operating system. TypeScript compiles to readable, standards-based JavaScript. 

If you have learned coding in languages like C++ or Java, you might already know what overloading is. Let's recall it. 

Overloading is a concept of calling a function with different sorts of arguments.



Source: Serokell
 

There are a lot of use of overloading functions, but in JavaScript, it occurs as it is a dynamically typed language. When both functions are compiled to JavaScript, their signature is totally identical. As JavaScript doesn't have types, we end up creating two functions taking the same number of arguments. So, TypeScript restricts us from creating such functions and thus provides us with a layer of assurance that our compiled code is properly written.

Function Overloads

In TypeScript, you can create multiple functions with the same name but different parameter types and return types. But, the number of parameters should be exactly the same, only the data type can differ.

Example:

function add(a: number, b: number): number;

function add(a: string, b: string): string;


function add(a: any, b: any): any {
    return a + b;
}
add(5, 20);
add(Hello, CodingNinjas);

 

Output:

 

The above example shows, we have the same add() function where two functions are declared and one function is implemented. 

We can see that the first signature has two parameters of type number, whereas the second signature has two parameters of the type string.

Since the return type can either be a number or string as per the first two function declarations, we must use compatible parameters and return type as any in the function definition.

The last function shows the implementation. We have assigned the function call as a type any, and in this way, we can do the function overloading concept here. Now, if we console.log this, we will be getting this result for a string as well as for a number. In the following way, we can achieve the function overloading concept.
 

Advantage of function overloading

  • Compiling a code is too fast since it saves memory space. 
  • Maintaining a code is easy.
  • It provides code reusability, which saves time and effort.
  • Readability of the program increases.

Function overloading in a class


This example will show you the concept of function overloading in class:

Class First {
    public folder(s: string): number;
    public folder(n: number): string;
    public folder(arg: any): any {
        if (typeof(arg) === 'number')
            return arg.toString();
        if (typeof(arg) === 'string')
            return arg.length;
    }
}
let obj = new First();
console.log("Result: " + obj.folder(101));
console.log("Length of String: " + obj.folder("CodingNinjas"));


After compiling the above TypeScript program,

Now,we will move to JavaScript code:

Class First {
    folder(arg) {
        if (typeof(arg) === 'number')
            return arg.toString();
        if (typeof(arg) === 'string')
            return arg.length;
    }
}
let obj = new First();
console.log("Result: " + obj.folder(101));
console.log("Length of String: " + obj.folder("CodingNinjas"));
You can also try this code with Online Javascript Compiler
Run Code

 

Output:

 

When to use function overloading?

When used the right way, Function overloading can significantly increase the usability of functions that may be invoked in multiple ways. That is especially useful during autocomplete: you get listed all the possible overloadings as separate records in autocomplete.

However, there are situations where you can skip function overloading but rather stick to the function signature.

 

For example, don't use the function overloading for optional parameters:

// Not recommended
function myFn(): string;

function myFn(param1: string): string;

function myFn(param1: string, param2: string): string;

function myFn(...args: string[]): string {
    // implementation...
}

 

Using Optional parameters in the function signature should be enough:

// OK
function myFn(param1 ? : string, param2: string): string {
    // implementation..
}

 

Do’s and Don’t 

 

Ordering

While resolving function calls, typeScript chooses the first matching overload. When an earlier overload is “more general” than a later overload, the later overload is effectively hidden and cannot be called. This is crucial for people who are “passing through” a value to your function. 

Don’t:

We don’t have to put more general overloads before the more specific overloads:

/* WRONG*/
declare function fnc(x: unknown): unknown;
declare function fnc(x: HTMLElement): number;
declare function fnc(x: HTMLDivElement): string;
var myElem: HTMLDivElement;
var x = fnc(myElem);

 

(*Note: x: unknown)

 

Do:

We have to sort overloads by putting the more specific signatures before more general signatures:

/*OK*/
declare function fnc(x: HTMLDivElement): string;
declare function fnc(x: HTMLElement): number;
declare function fnc(x: unknown): unknown;
var myElem: HTMLDivElement;
var x = fnc(myElem); 

 

(*Note: x: string)

Optional Parameter

The way typeScript resolves the signature compatibility is by seeing if there is any signature of the target that can be invoked with the arguments of the source, and extra arguments are allowed.

Don’t:

We do not need to write lot of overloads that differ only in trailing parameters:

/* WRONG */
interface Exp {
  	diff(one: string): number;
  	diff(one: string, two: string): number;
  	diff(one: string, two: string, three: boolean): number;
}

 

Do:

We can use optional parameters whenever possible:

/* OK */
interface Exp {
 	diff(one: string, two?: string, three?: boolean): number;
}

 

This collapse should only occur when all overloads have the same return type.

Union Type

This is crucial for those who are “passing through” a value to your function.

Don’t:

We can’t write overloads that differ by type in only one argument position:

/*WRONG*/
interface Moment {
 	utcOffset(): number;
 	utcOffset(b: number): Moment;
 	utcOffset(b: string): Moment;
}

 

Do:

We can use union types whenever possible:

/* OK */
interface Moment {
    utcOffset(): number;
    utcOffset(b: number | string): Moment;
}

 

We did not makeb’ optional here because the return types of the signatures differ.

Check out this article - Compile Time Polymorphism, Difference between argument and parameter

FAQs

  1. What is function overloading and overriding in JavaScript?
    JavaScript does not support overloading. JavaScript supports overriding, so if you declare two functions with the same name, the last one defined will override the previously defined version. Whenever a call is made to the function, the last defined one will get executed.
     
  2. What is the difference between function overloading and method overloading?
    In Method overloading, the method has a different signature. In a method, overriding methods have the same signature. Function Overloading is to "add" or "extend" more to the method's behaviour. Method overloading is used to achieve Compile time polymorphism; method overriding is used to attain run-time polymorphism.
     
  3. Can a static function be overloaded?
    A static method can not be overridden but can be overloaded in Java. Suppose you declare another static method with the same signature in the derived class. In that case, the static method of superclass will be hidden, and any call to that static method in subclass will go to the static method declared in that class itself.
     
  4. What is @types in TypeScript?
    The Type System signifies the different types of values supported by the language. This  System checks the validity of the supplied values before they are manipulated or stored by the program. The data types are further classified as: Built-in types and User-defined types

Key Takeaways

Function overloading in TypeScript initiates you to define functions that can be called in multiple ways.

Using function overloading requires defining the overload signatures: a set of functions with parameter and return types, but without a body.

If you are pursuing a new career in Web Development, we suggest you get your fundamentals crystal clear with our Full Stack Development course

This course will help you!

Live masterclass