Typescript Generics
Tags: typescript, generics, webdev
Published: 2024-06-29 16:12:24

Generics in Typescript are a feature that allows you to create components that can work with any data type while preserving type safety.  They provide a way to define functions, classes and interfaces without specifying the exact data types they will operate on in advance. Instead, you use type variables, usually represented by letters like <T>, to create a placeholder that will be replaced with a specific type when the component is used. 

```
function identity<T>(arg: T): T {
    return arg;
}


let numberIdentity = identity<number>(42); // Works with numbers
let stringIdentity = identity<string>("Hello"); // Works with strings

```
Let's consider an example,

```
function printData(data: number) {
    console.log("data: ", data);
}


printData(2);

```
In this example, we can not assign any string or object or boolean or array as the value of  ‘data’. Instead of previous example, we can rewrite the example as below,

```
function printData(data: number | string | boolean) {
    console.log("data: ", data);
}


printData(2);
printData("hello");
printData(true);
```
This example is a better approach than the previous one. In this example we can assign an argument value either number or string or boolean. But incase of complex argument or multiple argument it will be a little awkward looking and complicated. Instead of last example we can try another approach,

```
function printData<T>(data: T) {
    console.log("data: ", data);
}


printData(2);
printData("hello");
printData(true);
```
In this example we can pass any type of data as the value of argument ‘data’. We can pass string, boolean, number, obj, array without mentioning data type. 


How Generics work is TS:
Generics are like variables - to be precise , type variables - that store the type(for example number, string, boolean) as a value.


So, we can discuss generics as below:

```
function printData<T>(data: T) {
    console.log("data: ", data);
}


printData(2);
printData("hello");
printData(true);
```
In above example,
1) We can use type variable inside angular brackets after the fn name <T>
2) Then assign the type variable to the parameter data:T

Let explore bit more-
To use generics , we need to use angular brackets and then specify a type variable inside them. Developers generally use T, X, Y, V etc etc. But it can be anything depending upon preferences.
Even if we can pass an array of something or an object of something as an argument of data value, everything will be displayed without TS complaining.

```
function printData<T>(data: T) {
    console.log("data: ", data);
}


printData(2);
printData("hello");
printData(true);
printData([1, 2, 3, 4, 5, 6]);
printData([1, 2, 3, "hi"]);
printData({ name: "Ram", rollNo: 1 });
```

Let  see another example:


```
function printData<X,Y>(data1: X, data2: Y) {
    console.log("Output is: ", data1, data2);
}


printData("Hello", "World");
printData(123, ["Hi", 123]);
```

In the above example we passed two arguments to fn and used X and Y as type denotion for both parameters. X refers to the first value of the argument and Y refers to the second value of the arguments.
Here as well, the type of data1 and data2 are not specified explicitly because TS handles the type inference with the help of generics.