DEV Community

Cover image for Typescript Generics - What are they doing
Udayan Maurya
Udayan Maurya

Posted on

Typescript Generics - What are they doing

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.
const mapped = someFunction<T, U>(a, b)

// Type of a -> T and type of b -> U -- NO!
Enter fullscreen mode Exit fullscreen mode

(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

const identityFunction = (t) => t
Enter fullscreen mode Exit fullscreen mode

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.

const identityFunction = (t: unknown) => t
Enter fullscreen mode Exit fullscreen mode

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.

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

let num = identityFunction(785);
//  ^? unknown
Enter fullscreen mode Exit fullscreen mode

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:

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

let numBasic = 7856;
//  ^? number
Enter fullscreen mode Exit fullscreen mode

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 ๐ŸŽ‰

Generic types deploys typescript's inference mechanism to infer type of a function's input at usage ๐Ÿ”ฅ

Generic definition and breakdown

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

const identityFunction = <T>(t: T) => t
Enter fullscreen mode Exit fullscreen mode

Generic definition

generic definition

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

Just like static type assignment

let v1: string // v1 is assigned type string
Enter fullscreen mode Exit fullscreen mode

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 Arek Socha from Pixabay

Top comments (0)