TypeScript

Guides

TypeScript

Generics

Problem

Let's say we have a function that takes a callback function and call it.

Here's our function:

const mainFn = (cb) => cb()

And the functions that get passed to it are:

// One that returns a number
mainFn(
() => 5
)
// One that returns a string
mainFn(
() => 'string'
)
// Another than returns an array
mainFn(
() => [...] // Array that contain numbers
)

Our function mainFn can handle these easily, but an issue arose. We're using TypeScript, so we have to define the type of cb and mainFn return type.

Easiest solution is to hardcode the types:

const mainFn = (
cb: (() => number) | (() => string) | (() => number[])
): number | string | number[] => cb()

Now let's say mainFn will be called 100 times, with 100 different function functions, and each function has a different return type. Hardcoding a 100 type is overkill.

Wouldn't it be amazing to have a feature that makes it possible to pass the return type the moment we call the function? Here comes the Generics to help!

Solution

To fix that issue, we can define mainFn like this:

const mainFn = <T>(cb: () => T): T => cb()

The syntax of Generics is <>. Which works similar to parameters, but instead is a placeholder for types. T is the name we have given to the first placeholder slot. It could be <ReturnType> or <PotatoWalkingDownTheRoad.

Compared with parameters:

// Parameter syntax
// Wraps its placeholders with parenthesis
(num1, num2) => num1 + num2
// Generics syntax
// Wraps its placeholders with angle brackets
// and comes before the parameters
<T1, T2>(num1: T1, num2: T2) => num1 + num2

Back to our main issue, we can solve it by passing the type everytime we call mainFn:

// One that returns a number
// We define the return type as number through generics
mainFn<number>(
() => 5
)
// One that returns a string
// We define the return type as string through generics
mainFn<string>(
() => 'string'
)
// Another than returns an array
// We define the return type as number[] through generics
mainFn<number[]>(
() => [...] // Array that contain numbers
)