Typescript Generics - What are they doing
Tags: typescript, javascript, webdev, node
Published: 2023-11-13 02:56:25

Generics are usually considered most confusing part of Typescript. In this post I'll try to explain intuition behind generics and hopefully make them easier to use!

## Common beginner confusions

(1) Generics will do some type interpretation at runtime

* **No** - Typescript is only available at compile time and not runtime!

(2) Generics map to input arguments

- **No** - Generic types can map to any input arguments as designed by developer.

```ts
const mapped = someFunction<T, U>(a, b)

// Type of a -> T and type of b -> U -- NO!
```

(3) Generics make my code look ugly 😖

- No magic bullet to solve this. However, if you leverage typescript's inference properly you can minimize this problem.

## What problem generics solve

Let's say we have an identity function 

```ts
const identityFunction = (t) => t
```

And we want:

1. Function should accept any type of input
2. Function's return type should match input's type

How can we type this function to achieve both objectives?

#### Naive solution

Statically type the input to be `unknown` type. `unknown` is top type in typescript's type system and every other type can be assigned to `unknown`.

```ts
const identityFunction = (t: unknown) => t
```

However, this approach fails to achieve second objective that is type of function's return value is always `unknown` regardless of the type of input.

```ts
let str = identityFunction('hello');
//  ^? unknown

let num = identityFunction(785);
//  ^? unknown
```

So ideally we want the type of function's input to be inferred when we use the function.

Typescript has such inference mechanism as we use it all the time:

```ts
let strBasic = "world";
//  ^? string

let numBasic = 7856;
//  ^? number
```

If there was a technique to leverage this Typescript's inference mechanism to infer the type of a function's input at usage we can solve our problem.

And that technique is **Generic types** :tada:

> Generic types deploys typescript's inference mechanism to infer type of a function's input at usage :fire:


## Generic definition and breakdown

So if we redefine the identity function using generic type it looks like:

```ts
const identityFunction = <T>(t: T) => t
```

#### Generic definition


![generic definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxxjp6zki213ue15kw02.png)

Generic function will infer the type of input at usage. But we still need a way to reference that type in our function body while defining the function. 
This type cannot be any static type such as `any` or `unknown` it needs to be dynamically inferred. Therefore, we need a special typescript variable `T` to store this dynamic type.

#### Generic assignment and inference

![Generic inference](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xkl40qi4giso383wglwm.png)

Just like static type assignment 

```ts
let v1: string // v1 is assigned type string
```

we use `:` to assign type of input.
 
Additionally, in case of generics, type of input gets inferred at this step and is stored in variable `T`.

Type inference only happens at the level of arguments within parentheses `()` and no where else in function body.



_Image by <a href="https://pixabay.com/users/qimono-1962238/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2125169">Arek Socha</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2125169">Pixabay</a>_