Last updated: Feb 29, 2024
Reading timeยท7 min
If you got the error "Overload signature not compatible with Implementation signature", click on the second subheading.
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.
Here is an example of how the error occurs.
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.
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.
function sum() {} export {}; // ๐๏ธ make file ES Module
In short, this sometimes glitches because of how legacy script files globalize declarations.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
// โ๏ธ 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.
// โ Implementation signature compatible with Overload signatures function example(str: string): string; function example(num: number): number; function example(arg: string | number): number | string {}
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.
Here is an example of how the error occurs.
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
.
string
as a parameter, so it isn't compatible with the second overload signature.To solve the error, we have to make sure the implementation signature is compatible with all of the overload signatures.
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.
Here is a complete example of a function with 2 overload signatures.
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.
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);
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.
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.
// โ๏ธ 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.
// โ 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.
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.
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.
You can learn more about the related topics by checking out the following tutorials: