Duplicate function implementation in TypeScript [Solved]

avatar
Borislav Hadzhiev

Last updated: Feb 29, 2024
7 min

banner

# Table of Contents

  1. Duplicate function implementation in TypeScript
  2. Overload signature not compatible with Implementation signature

If you got the error "Overload signature not compatible with Implementation signature", click on the second subheading.

# Duplicate function implementation in TypeScript

The error "Duplicate function implementation" occurs when we define an implementation for a function with the same name multiple times in the same file.

To solve the error, rename the second function or use overloads by specifying multiple signatures, not multiple implementations.

duplicate function implementation

# Having multiple functions with the same name

Here is an example of how the error occurs.

index.ts
function sum() {} // โ›”๏ธ Error: Duplicate function implementation.ts(2393) function sum() {}

We defined a function named sum twice in the same file and got the error.

This also happens with class methods - a class cannot have multiple methods with the same name.

If this is the cause of the error, give the second function a different name.

# Having a glitch due to legacy script files

Another cause of the error is having a glitch due to legacy script files.

If you only have a single definition for the function in the file, add the export {} line to your file to make it an ES Module.

index.ts
function sum() {} export {}; // ๐Ÿ‘ˆ๏ธ make file ES Module
The code for this article is available on GitHub

In short, this sometimes glitches because of how legacy script files globalize declarations.

# Trying to use function overloads

Another common cause of the error is trying to use function overloads, but mistakenly providing multiple implementations instead of multiple signatures for the function.

The syntax for function overloads looks as follows.

index.ts
function reverse(a: string): string; function reverse(a: string[]): string[]; function reverse(a: string | string[]): string | string[] { // your implementation return 'bobbyhadz.com' }

Notice that we only use curly braces {} when specifying the function implementation.

If you add curly braces on multiple lines, you are declaring multiple implementations for the same function which causes the error.

We basically supply multiple function types for the same function but there is only one implementation of the function.

Here is a complete example of a function with 2 overload signatures.

index.ts
function createDate(timestamp: number): Date; function createDate(year: number, month: number, day: number): Date; function createDate( yearOrTimestamp: number, month?: number, day?: number, ): Date { if (month !== undefined && day !== undefined) { return new Date(yearOrTimestamp, month, day); } return new Date(yearOrTimestamp); } const date1 = createDate(1647778643657); console.log(date1); // ๐Ÿ‘‰๏ธ Sun Mar 20 2022 const date2 = createDate(2023, 9, 24); console.log(date2); // ๐Ÿ‘‰๏ธ Tue Oct 24 2023

complete example of function with 2 overload signatures

The code for this article is available on GitHub

The first two lines are called the overload signatures, the third line is the function implementation.

The Date() constructor can be passed different parameters to create a Date object.

In the first signature, the function takes a timestamp (number) parameter and returns a Date object.

In the second signature, the function takes 3 comma-separated parameters of type number and returns a Date object.

Note that the implementation signature of the function cannot be called directly, you have to call one of the overload signatures.
index.ts
function createDate(timestamp: number): Date; function createDate(year: number, month: number, day: number): Date; function createDate( yearOrTimestamp: number, month?: number, day?: number, ): Date { if (month !== undefined && day !== undefined) { return new Date(yearOrTimestamp, month, day); } return new Date(yearOrTimestamp); } // โ›”๏ธ Error const date3 = createDate(2023, 9);

Even though the line where we call the createDate function satisfies its implementation signature because the function has 2 optional parameters, we get an error.

The implementation signature of the function cannot be called directly, you have to call one of the overload signatures.

None of the overload signatures expect 2 arguments. The first overload signature expects 1 and the second expects 3.

When writing your function implementation, make sure it is compatible with the overload signatures.

index.ts
function example(str: string): void; // โ›”๏ธ Error: This overload signature is not // compatible with its implementation signature. function example(num: number): void; function example(arg: string) {}

The implementation signature takes a parameter of type string, but the second overload signature takes a parameter of type number.

The implementation signature has to be compatible with all overload signatures.

index.ts
function example(str: string): void; function example(num: number): void; function example(arg: string | number) {}

Now the parameter in the implementation signature has a compatible type with all of the overload signatures.

If one of your overload signatures takes more parameters than the others, mark them as optional in your implementation signature.

index.ts
function example(str: string): void; function example(num: number, num2: number): void; function example(arg: string | number, num2?: number) {}

You should also make sure that the return types of the overload signatures and the implementation signature are compatible.

index.ts
// โ›”๏ธ Error function example(str: string): string; function example(num: number): number; function example(arg: string | number): number {}

Notice that the first overload signature has a return type of string, and the second has a return type of number.

The implementation signature cannot have a return type of number, because it is not compatible with the first overload signature.

index.ts
// โœ… Implementation signature compatible with Overload signatures function example(str: string): string; function example(num: number): number; function example(arg: string | number): number | string {}

# Overload signature not compatible with Implementation signature

The error "This overload signature is not compatible with its implementation signature" occurs when the implementation signature of the function is not compatible with all of its overload signatures.

To solve the error, make the implementation compatible with all overload signatures.

overload signature not compatible implementation

Here is an example of how the error occurs.

index.ts
function example(str: string): void; // โ›”๏ธ Error: This overload signature is not compatible with its implementation signature. function example(num: number): void; function example(arg: string) {}

The first two lines are called the overload signatures and the third line is the function implementation.

The first overload signature takes a string as a parameter and the second a number.

The implementation signature takes a string as a parameter, so it isn't compatible with the second overload signature.

# Make sure the implementation signature is compatible with the overload signatures

To solve the error, we have to make sure the implementation signature is compatible with all of the overload signatures.

index.ts
function example(str: string): void; function example(num: number): void; function example(arg: string | number) {}
The code for this article is available on GitHub

Now the parameter in the implementation signature has a compatible type with all of the overload signatures.

Here is a complete example of a function with 2 overload signatures.

index.ts
function createDate(timestamp: number): Date; function createDate(year: number, month: number, day: number): Date; function createDate( yearOrTimestamp: number, month?: number, // ๐Ÿ‘ˆ๏ธ mark optional day?: number, // ๐Ÿ‘ˆ๏ธ mark optional ): Date { if (month !== undefined && day !== undefined) { return new Date(yearOrTimestamp, month, day); } return new Date(yearOrTimestamp); } const date1 = createDate(1647474643657); console.log(date1); // ๐Ÿ‘‰๏ธ Thu Mar 17 2022 const date2 = createDate(2023, 4, 24); console.log(date2); // ๐Ÿ‘‰๏ธ Wed May 24 2023

The Date() constructor can be passed different parameters to create a Date object.

In the first signature, the function takes a timestamp (number) parameter and returns a Date object.

Notice that the first overload signature only takes a single parameter, whereas the second takes 3 parameters.

In this case, we have to mark the second and third parameters as optional.

# The implementation signature cannot be called directly

IMPORTANT: The implementation signature of the function cannot be called directly, you have to call one of the overload signatures.
index.ts
function createDate(timestamp: number): Date; function createDate(year: number, month: number, day: number): Date; function createDate( yearOrTimestamp: number, month?: number, day?: number, ): Date { if (month !== undefined && day !== undefined) { return new Date(yearOrTimestamp, month, day); } return new Date(yearOrTimestamp); } // โ›”๏ธ Error: No overload expects 2 arguments, // but overloads do exist that expect either 1 or 3 arguments.ts(2575) const date3 = createDate(2023, 4);
The code for this article is available on GitHub

Even though the line where we call the createDate function satisfies its implementation signature, because the function has 2 optional parameters, we get an error.

The implementation signature of the function cannot be called directly, you have to call one of the overload signatures.

None of the overload signatures expect 2 arguments. The first overload signature expects 1 and the second expects 3.

You should also make sure that the return types of the overload signatures and the implementation signature are compatible.

index.ts
// โ›”๏ธ Error: This overload signature is not // compatible with its implementation signature.ts(2394) function example(str: string): string; function example(num: number): number; function example(arg: string | number): number {}

Notice that the first overload signature has a return type of string, and the second has a return type of number.

The implementation signature cannot have a return type of number, because it is not compatible with the first overload signature.

index.ts
// โœ… Implementation signature compatible with Overload signatures function example(str: string): string; function example(num: number): number; function example(arg: string | number): number | string {}

Just like in the example with the createDate function, if one of your overload signatures takes more parameters than the others, mark them as optional in your implementation signature.

index.ts
function example(str: string): void; function example(num: number, num2: number): void; function example(strOrNum: string | number, num2?: number) {}

Now consumers of our function are able to call it with a single parameter - a string which would satisfy the first overload signature.

They are also able to call it with 2 parameters of type number but the function cannot be invoked with a single parameter of type number, even though its second parameter is marked as optional.

index.ts
function example(str: string): void; function example(num: number, num2: number): void; function example(strOrNum: string | number, num2?: number) {} // โœ… OK example('bobbyhadz.com'); // โœ… OK example(1, 2); // โ›”๏ธ Error: The call would have succeeded against // this implementation, but implementation // signatures of overloads are not externally visible. example(1);

The implementation signature of the function cannot be called directly, you have to call one of the overload signatures.

If you need to pass a function as a parameter, check out the following article.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev