Generics in TypeScript
Generics are language independent concept(exist in C++ as well).
Generics are considered to be the most important and difficult topics to understand in TypeScript but it’s not that difficult btw. So before we take a deep dive into generics, let us first consider a problem and let’s see how that problem can be solved using generics.
Let’s we have a function that needs to return the first element of an array. Array can be of type either string or integer.
To solve the above problem, we can think of an approach which seems to be very straight forward : -
type Input = number | string;
function getFirstElement(arr: Input[]) {
return arr[0];
}
const value = getFirstElement(["rishu","kumar"]);
console.log(value.toUpperCase());
Do you really think that the above code will do the job for us? The simple answer is a big no. Since the argument accepted by our function is of type both number and string, TypeScript thinks that the value it will return will also be type either number or sting. Thus we will get an error at the line “console.log(value.toUpperCase());” because we can convert only strings to upper case or lower case and not to a number but according to TypeScript “value” is of any type i.e. number or string.
Now, how to solve this issue?
We need Generics!
So, What really generics are?
Generics enable us to create components that work with any datatype while still providing compile-time type safety.
Oh! , seems like another bookish definition? Bear with me, The smallest example of generics can be taken as :-
If there is a function called “Identity” that let’s say take a string or a number as an input.
Rather than doing what we did previously, we can do like this :-
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString");
let output2 = identity<number>(100);
The <T> means, this function can be called for “generic” value. Can be a string or can be a number. And, “identity<string>” means, I am calling this function with T set to string. Same goes for “identity<number>”.
The above code can be understand by :-
Suppose we created two “identity” functions in which one take number as argument and another take string as argument.
function identity1(arg: number) {
return arg;
}
function identity2(arg: string) {
areturn arg;
}
let output1 = identity1(100);
let output2 = identity2("myString");
Now, solving our original problem in which we have to return the first element of an array where array can be of type string or number.
function getFirstElement<T>(arr:T[]) {
return arr[0];
}
const element = getFirstElement(["rishu","kumar"]);
console.log(element.toUpperCase());
Now, we are done with our problem, toUpperCase() is not erroring out.