Intro to Typescript generics (a must know) 
Tags: typescript, webdev
Published: 2020-09-22 19:37:57

[*Photo by Anas Alshanti (Unsplash)*](https://unsplash.com/photos/feXpdV001o4)

If you are a Typescript developer and haven't already started using generics, **you are missing out**! The word itself is quite scary, 🧟*generics*👻. But fear not, it is really simple and very useful!

## What the *!#@ is generics any way?
Since JavaScript is a dynamic language generics is not a thing there. Everything is kind of generic.

You would have go down the road to C#,Java or *Tyescript* to find definitions and use cases for generics. 

Generics are enabling us [to create a component that can work over a variety of types rather than a single one](https://www.typescriptlang.org/docs/handbook/generics.html). (That line is from the Typescript docs, and you should go there later to really dig deeper...)

When creating a function, for example, some functions would be great if they could work with different types. Or really any type! And that is easy of course, just slap some `:any` magic there and the function is generic. Right?

![Image of man with the caption: Well yes but actually no](https://media.giphy.com/media/SVgKToBLI6S6DUye1Y/giphy.gif)

Generic functions accept many types while remaining the type info!

## One example, please!

[The code can be found here](https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIGUEHsooN4BQyxyADgDZwCe0AcnALYQBcyAzmFKAOYDcRJANbBy5NqxABXBgCNo-EsgAmEOGAAW45FNnyCAXwIFsIDu2y5xGCxADaAXWQBeZLYHFCixRWp1GLZAAidGAGLBBAgBp3LxU1TVYAJgBmaK8hETFWZMSY-TSST3SyShooeiZWQIApLHU4CIL0uI0tAEYABiavYVEtRIBOPIJ7IxhJEAQwYHDkOAA3bgAeABUAPgAKYEgGcRWHSORuCDBIKFYNsGYVgEpnNe1pOSg7ouITMzZpZ2RtiF2AHS4JSSJAbDaIBCHBCSKAve5HE5nDYwuF3ADUcwQUOQHRuMVwYFhIHY3wA9L8dmwAeQICBuBoDEYPlhaTSsNwIYsNmwbGxDqQEaQAb0xDcbkA)

Say we have a simple interface in our game app that looks like this
```typescript
interface IScore {
    playerName: string;
    kills: number;
    deaths: number;
}
```

Now we need some way of calculating averages of arrays with objects of this interface. So we write something like this:
```typescript
function avg(items:IScore[], getter: (t:IScore) => number) {
  const sum = items.reduce((acc, curr) => getter(curr) + acc, 0)
  return sum / items.length
}
```
Simple, we take an array of scores as the first argument, and the second is a function that will get the number property used to calculate the average.

But this function only works for one type, the `IScore`. That is not cool, this function could be used with other types as well. __As a generic function__, so we could do like this, right:

```typescript
function avg(items:any[], getter: (t:any) => number){/*...*/}
```
Great, now it works with literally `:any` type. But, wait. Isn't the whole point of Typescript not to do like this. Dynamic scary things can happen now, what if we remove a property from the interface `Cannot read property X of...` errors will haunt us when the getter is not finding the property name. 

### Enter generics (the real type)

To make this function a generic function, and add type checks, we only need to alter the signature of the function. A generic type is annotated with the <> signs before the function arguments. Like this: ```typescript
function avg<T>(...
```
The __T__ part is the name of your generic type. This could almost be anything, common (what I have seen at least) is to use T if there is only one type. Yes, T is for Type. You could be more specific, it's encouraged when using multiple generic types in one function like `<TFriend, TEnemy>` 

The next step is to simply replace the `:any` parts with `:T` to make the function generic:
```typescript
function avg<T>(items:T[], getter: (t:T) => number){/*...*/}
```
Now we could just do something like this

```typescript
const deathAvg = avg<IScore>(scores, x => x.deaths)
```
Or even this:
```typescript
const deathAvg = avg(scores, x => x.deaths)
```
Typescript will infer the type to use in the generic function, and use that one automatically

### Extra credits

While this function could actually use any type given to it (a string array could calculate the average char length of all words) we can for the sake of example restrict this one to only accept arrays of objects. This would be called a __constraint__ on the generic type. 

Meaning, the generic type cannot be anything. It must fulfill some rule(s). This information is added to the generic signature with the keyword `extends`. We say the given type `T` must extend something. In our example `object`. So we just change to this:

```typescript
function avg<T extends object>(items:T[]...
```

## One more example?
You could also make your types generic. A lot of API endpoints response types have the same basic shape. They contain information about the total number of items in the database, response, and if there is more data to fetch. And then of course the list of items. So I could write a type collection for everything like this:
```typescript
interface IUsersCollection {
  values: IUser[];
  totalInDatabase: number;
  totalInResponse: number;
  isLast: boolean
}

interface IDatabaseCollection {
  values: IDatabase[];
  totalInDatabase: number;
  totalInResponse: number;
  isLast: boolean
}

```
That is not fun. Not at all. Think only if we add one property to the response...

Simply do this 
```typescript
interface ICollection<TType> {
  values: TType[];
  totalInDatabase: number;
  totalInResponse: number;
  isLast: boolean
}
interface IUsersCollection extends ICollection<IUser> {}

interface IDatabaseCollection extends ICollection<IDatabase> {}

```
And it works great with `type` as well:

```typescript
type Collection<TType> = {
  values: TType[];
  /* etc. */
}
```

And you could just put your type definition straight there 
```typescript
type UsersCollection = Collection<{
  id: number;
  name: string;
  /* etc.*/
}>
```
## Summary
So generics, saves you time both in making smarter types/interfaces and implementing type safety where you would otherwise just mess around with `:any`. 

And this is not all. Generics can be used in several other fun and useful ways!