Getting friendly with TypeScript (part 3): Generics
This article is intended for anyone who is trying to get to grips with the world of TypeScript.
It is recommended to read part 1 and part 2 before reading this article.
This article will cover:
- Generics 🥭
- Lots of simple code examples 🪄
In part 1 we introduced the basic concepts of TypeScript and in part 2 we delved a little bit deeper into these concepts. In part 3, we’re going to venture further still and expand our knowledge as we introduce some new topics.
This is still very much a ‘beginner’s guide’ and we’re going to keep things simple, so sit back and relax. Enjoy the ride.
Generics
At first, I found Generics really difficult to understand. But after a lot of reading and tutorials, I’ve found a simpler way to understand them.
What are Generics? I hear you ask…
Generics basically provide a way to create reusable components.
This probably means nothing to you right now, but hopefully the following examples will make it clear.
The most simple example of a Generic is Array.
NOTE: When we create arrays in TypeScript, we have to specify the type of the array between angle brackets, e.g.,
Array<string>
would be a string array.
An array without Generics could contain anything:
In the screenshots above, you can see that we create a type called anyArray
which takes the any
type. This means that the array can hold any values.
Essentially, we ‘turn off’ TypeScript when we use the
any
type.
An array with Generics, however, can describe the values that the array contains:
It’s called a Generic because we can put any type between the <>
and this will change the array type.
numArray
will only allow an array of numbersstringArray
will only allow an array of stringbooleanArray
will only allow an array of booleans
The examples above are nice but they don’t allow for flexibility. This is where Generics really shine. Let’s take a look with some more examples…
First, it’s good to note that <T>
is typically used to describe a Generic. This T
simply stands for ‘type’.
In the above screenshot, we have created an interface Person
which has firstName
, secondName
, age
and randomInfo
as properties.
This big difference to previous examples we have seen so far is that we have Person<T>
and our randomInfo
property is of type T
. Ok, what on earth does this mean?
Well, by using <T>
, this makes the interface more flexible. You can add any type here.
In the example above, I have assigned Person<object>
and so randomInfo
has to be of type object.
If we try to assign a value that is incompatible with type object
, we get an error:
We can also use Generics for functions:
In the example above, we have created a function called returnLastElement
which takes an array of numbers and returns the last number in this array.
This function works fine, but we can make it even more flexible by using Generics:
In the example above, we have changed the array type that the function accepts from Array<number>
to Array<T>
which means the function can accept an array of any type, and will return the last element of this array.
By using <T>
instead of <number>
, this makes the function more flexible.
NOTE: The syntax looks a little scary here, but don’t worry about it too much. Just know that this is the syntax you should for Generics in functions.
More Generic examples:
The example above shows us how we can create a tuple that must take the same type for both arguments.
With this Pair
type, we can create other types. The example above creates a type Coordinate
which is type Pair<number>
meaning it must be a tuple of two numbers.
We can also use the Pair
type to create a time span. In the example above, we create a type TimeSpan
which has to be a tuple of two dates.
So, hopefully now you have a better idea of what Generics are. You don’t need to be an expert at this point, but just having a basic understanding of Generics and how they work will help you to understand a lot more TypeScript code.
For example, you’re now ready to understand Utility types.
Urgh, another new thing. What are these then?
If you’re feeling curious, you can read about some of the most common utility types in the next article: ‘Getting friendly with TypeScript: part 4’
🍉 🍍 🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉 🍍🍉
If you enjoyed this article, you might enjoy other articles from the ‘Getting friendly with…’ series:
Getting friendly with the terminal: a super-friendly beginner’s guide
Getting friendly with git: a super-friendly beginner’s guide
Getting friendly with TypeScript (part 1): a super-friendly beginner’s guide
Getting friendly with TypeScript (part 2): a super-friendly beginner’s guide
Keep challenging yourself and remember, being uncomfortable means you are growing.