Learn TypeScript

Method overloading

Method overloading

In this lesson, we will learn what method overloading is, when it is useful, and how to implement it.

What is method overloading?

Method overloading is where a single method can have multiple signatures but still be strongly-typed.

The following example contains two calls to an overloaded method:

logger.log("An important message");
logger.log("An important message in the orders module", "Orders");

This provides a much nicer API to a consumer than the following, where different methods are used:

logger.logMessage("An important message");
logger.logMessageAndModule(
"An important message in the orders module",
"Orders"
);

Overloading works on regular functions as well as class methods:

log("An important message");
log("An important message in the orders module", "Orders");

The syntax for method overloading

Overloaded methods are declared with all their signatures followed by the implementation of the method:

methodName(params1): returnType1
methodName(params2): returnType2
methodName(params3): returnType3 // implementation signature
{
// implementation
}

The last signature, just above the implementation, is called the implementation signature.

The parameter types and the return types in the signatures can be different, but they need to be compatible with the implementation signature. The implementation needs to check what parameters have been passed and take the necessary action.

A method overloading example

We are going to explore method overloading in an exercise.

TypeScriptOpen exercise in CodeSandbox

The code contains a Product class that is familiar from previous lessons. The code also includes a Products class, which manages a collection of Product instances.

We will implement a filter method in the Products class that can filter by the name and the price.

  • Add a filter method in the Products class that takes in name and price parameters and returns the products filtered by the name and price passed into it. Explicitly define the return type in the signature.
  • Consume the filter method in the products variable, outputting its result to the console. Verify the process works as expected.
console.log(products.filter("Table", 400));
  • Overload the filter method by adding a signature that contains just the name parameter. Don't change the implementation yet.
filter(name: string): Product[]
filter(name: string, price: number): Product[] {
...
}
🤔

Notice that a type error is raised. What is the problem?

  • Resolve the problem by making the implementation signature price parameter optional.

The overload signatures need to fit into the implementation signature. This generally means that some of the implementation signature parameters need to be optional.

  • Change the implementation of the method so that it works with both signatures:
  • Consume the filter method as follows:
console.log(products.filter("Table", 300));
🤔

Notice that a type error is raised. What is the problem?

  • Add an overload signature for when the name and price parameters are both passed in:
  • Consume the filter method again. Type the code out manually rather than copying and pasting it.
console.log(products.filter("Chair", 100));

Notice how intellisense informs us of the different signatures available:

Overload signature intellisense

Neat!

The chair product is output to the console as we expect.

Summary

Overloaded methods in TypeScript are a little less flexible than you may have experienced in other languages because each overload signature needs to be compatible with the implementation signature. However, they do help us provide a nice API to consumers in certain situations, and the enhanced intellisense is a nice touch.

In the next lesson, we will learn how to extend a class.

© 2024 Carl Rippon
Privacy Policy
This site uses cookies. Click here to find out more