TypeScript generic types

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
No comments yet. Be the first to comment.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

When working with types in TypeScript, we assume that we know what kind of type we will be working with.
For instance to define this log function:
const logAndReturn = (input: string): string => {
console.log(input);
return input;
};
In this simple function, we expect a string, return a string, and that's it.
But why should this be limited to just strings?
What if we try to pass a number?

Hmm, that's a bit silly. We can't pass numbers to this function. And it makes total sense.
One possible way of solving this would be to use any as the type.
const logAndReturn = (input: any): any => {
console.log(input);
return input;
};
But using this makes it impossible to identify the type from outside. It's basically as if you didn't use TypeScript at this point.
By the use of outside, I mean wherever we call this function, you should see what type it is being cast to like so:

So what then?
This is precisely where generic types come in handy. They can be used to identify that specific called function as a type.
Making the function itself unaware of which type it's working with.
To identify a generic type, you must prefix the function with <Type> where Type is the generic variable.
Note: We often use
Tfor generic types. However, it's not limited to any name.
Let's redo the above function as a generic typed function.
const logAndReturn = <T>(input: T): T => {
console.log(input);
return input;
};
Now, if we want to use this function and pass a string, we can do the following:
logAndReturn<string>('a string');
And on inspection, it states the following:

And if we want to convert this to our number, we can change the generic type used.
logAndReturn<number>(123);

As you can see, this is super powerful as we don't need to know the type upfront, but keep the reference to the correct types.
This method is not limited to these existing types. We can even define a custom interface that we want to use.
interface User {
firstname: string;
lastname: string;
}
logAndReturn<User>({firstname: 'Chris', lastname: 'Bongers'});
And in that case, our function will expect the User type.
I hope you got an excellent first look at Generic types and how we can use them. I'll go deeper into specific use-cases that will shed a broader light on them in the following articles.
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter