When working with C++, you might expect the initial code snippet to function properly. In C++, using a function template like the one shown below is valid:
template <class T>
T add(T a, T b) {
return a+b;
}
However, in C++, this is considered a function template, which means that multiple functions are generated from it as needed. If you attempt to use the function with a type that lacks the +
operator, such as add(boolean, boolean)
, the template instantiation will fail during compilation.1
In contrast, Typescript only creates a single function based on your generic, which looks something like this:
function add(a, b){
return a+b;
}
The purpose of generics in Typescript is to perform compile-time checks to ensure that only legal arguments are passed into this singular function.
While this function would fail at runtime if the arguments do not support the +
operator, Typescript restricts the usage of the +
operator unless the argument types explicitly support it.
For example, the add
function enforces that both arguments have the same type, disallowing something like add(2, true)
but permitting add(true, true)
. On the other hand, the greet
function would also reject the latter due to true
not being an instance of a number.
These concepts represent the fundamental principles underlying how languages implement generics: either by recompiling or compiling once and enforcing restrictions. Languages like C++, Rust, and D adopt the recompile approach known as monomorphization, while Typescript, Java, and Python opt for the latter method of compiling a single polymorphic function and limiting its usage. Go, on the other hand, utilizes an intriguing hybrid approach.
1) It should be noted that when there are multiple add
templates, the compiler will search for other suitable templates before throwing an error, following the concept of SFINAE