Incomprehensible typescript generic function overload

Viewed 59

While studying TypeScript, I noticed a strange behavior.

function concat5<T>(strs: T, strs2: T): T;
function concat5(strs: string, strs2: string) {
    return strs + strs2;
}

concat5(123, 12);
concat5({a:1}, {b:2});

I think this code is an error. However, no error occurs in the IDE.

Why?

1 Answers

TypeScript is not same as Java/C#, where Type is part of the runtime, JavaScript has no runtime type restriction, there is no casting errors, there is no type conversion errors, all Types in TypeScript only stays in the Editor and in Compiler, after compilation, all types go away. And JavaScript also does not have function overloading, as there are no types, every type of object can be passed in function as argument.

In your case, Function overloads are only declarations, and cannot automatically detect errors based on the implementation. It can only detect errors based on Types Specified.

function concat5<T>(strs: T, strs2: T): T; only tells that both strs and strs2 should be of same type, there is no restriction on that T can be.

Following results in the error, where it says that the implementation does not match declaration.

function concat5<T>(strs: T, strs2: number): T;
function concat5(strs: string, strs2: string) {
    return strs + strs2;
}

Lets see this example,

function concat5<T extends number>(strs: T, strs2: T): T;
function concat5(strs: string, strs2: string) {
    return strs + strs2;
}
function concat5<T1 extends number, T2>(strs: T1, strs2: T2): T1;
function concat5(strs: string, strs2: string) {
    return strs + strs2;
}

The reason this does not give any error is, JavaScript can accept any object for string input as it will eventually convert all objects to string, so it does not give wrong implementation error in this case. As long as both parameters are are not explicitly specified.

For Fun If you open Chrome's console and type {} + {}, you will see result [object Object][object Object]. JavaScript allows concatenation of any two types, they are converted to string.

>{} + 2
< 2
>2 + {}
<"2[object Object]"
>null + 2
<2
>2 + undefined
<NaN
>2 + (function(){ return 3; })
<"2function(){ return 3; }"

Related