Classy way of using Typescript Generics
Tags: typescript, javascript, react
Published: 2021-01-06 13:51:04

---
published: true
title: Classy way of using Typescript Generics
description: Within the realms of Object-Oriented Programming, generic types are a very common and useful way to build components which can work with a variety of types instead of only one. Fortunately for us, we can do the same generic types in functional programming using TypeScript Generics.
tags:
  - typescript
  - javascript
  - react
---
## Overview

Within the realms of Object-Oriented Programming, generic types are a very common and useful way to build components which can work with a variety of types instead of only one. Fortunately for us, we can do the same generic types in functional programming using TypeScript Generics.

## Using generic parameters

1. Simple example

A simple generic parameter in a function looks like this:

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

A generic type can be defined by using `<GenericAnnotation>` after the name of our function. Then simply specify the type of the argument to be the generic type. The return value of a function can also be defined as a generic type, e.g. `myFunc<T>(arg: any): T`

2. More Interesting Example

Let's have the following interface `IUserDetails` which specifies different user properties:

```
interface IUserDetails {
  firstName: string;
  lastName: string;
  age: number;
  dob: Date;
}
```

For the sake of this example, let's imagine that each user property needs to be updated separately. One way to do this is by writing a function for each property which can be strongly typed independently for each property. <br/>
Instead of doing that, let's build a *generic* function which will allow to pass any of the user properties and their correct types. Here is how that might look like:

```
function updateUserDetails<
  TKey extends keyof IUserDetails,
  TValue extends IUserDetails[TKey]
>(key: TKey, value: TValue) {
  // Update user details
}
```

Pretty cool isn't it? Let's see what the generic type constraints are doing. <br/>
There are two generics in the function, one for the key of the user property, `TKey`, and the other for the value of it, `TValue`.

* `TKey` has a defined type constaint, specifying that it can only be one of the keys of `IUserDetails` interface. 
* `TValue` has a defined type constraint, specifying that the type can only be the type of the defined user property.

Calling the function like this: `updateUserDetails("dob", "Jack")` will throw a type error as the `dob` property of the interface expects a type of Date, but executing the function like `updateUserDetails("firstName", "Jack")` will work as it's passing the correct type for`firstName` property.

## Using Generic types when building React components

Typescript Generics can also be applied when building React components. <br/>
Here is an example. Let's build a List which can receive any types of list items with predefined generic constraints.

This is the bare minimum a List item object needs to have:

```
interface IBaseListItem {
  id: string;
  name: string;
}
```

The props of the list will look like this:

```
interface IListProps<T extends IBaseListItem> {
  title: string;
  items: T[];
}
```

The `items[]` property is defined as a generic type with a constaint which provides the bare minimum the type needs to have in order to be accepted, in this case is `IBaseListItem`. <br/>

The component definition can look like this:

```
function List<T extends IBaseListItem>(props: IListProps<T>) {
  return (
    <ul>
      {props.items.map((it) => (
        <li key={it.id}>{it.name}</li>
      ))}
    </ul>
  );
}
```

The react component has defined generic type which is provided to the generic props `IListProps`. As the generic type of the function has the same generic constraint as the `IListProps`, the generic type will be accepted.