Check out a free preview of the full TypeScript Fundamentals course:
The "Introducing Generics" Lesson is part of the full, TypeScript Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Mike introduces generics, which allow the reuse of code across types, interfaces, and functions.

Get Unlimited Access Now

Transcript from the "Introducing Generics" Lesson

[00:00:00]
>> Mike North: Generics only usable in TypeScript, cuz this has everything to do with types. The purpose of generics is we want to be able to reuse code across many types, interfaces, functions. We wanna be able to leverage it multiple times and we need to express a relationship between, types a constraint like you're going to give me an argument of a particular type and I'm going to return a particular type that depends on the type of argument you passed me.

[00:00:30] So in this case we've got something that is exactly that. It's a function called gimmieFive and whatever you give it it'll return an array with five of that thing in it. Right, so in the case where we pass it three the type it returns is a number array.

[00:00:47] If we give it the string egg then the value of eggs is gonna be an array, with five of the string egg in it. So here's how it works, you see after the name of the function we have what is called the type parameter. That needs to go in angle brackets, T is a convention you'll see.

[00:01:10] Usually it's a single letter that people use for this which is a convention left over from C++ days. These were known as template parameters in C++, they are known as generics in Java and also generics here.
>> Mike North: And so we define a type parameter and now that's sort of a placeholder for a type to be determined later.

[00:01:30] And then we say you're going to give me x, which is of a certain type and I'm going to return an array of that certain type. So this function here is sort of defined in an abstract way, but as soon as we pass a value into it, now we know exactly what that's going to be, right?

[00:01:46] We pass it a number and so, yes, T is a number for that first invocation. And for the second one, T is string for that second invocation.
>> Mike North: So this takes a little getting used to and particularly designing good functions around generics. It is something that can certainly be done very poorly if you don't feel like overly constraining things or if you're not using the generic properly.

[00:02:21] In this case, it's useful because we don't have to return an array of any, like we could've expressed this. As gimmieFive and I take an any and I return an array of any's. But we would've basically had to cast that immediately thereafter, in order to use that array in something that would want an array of numbers.

[00:02:42] So we don't get that type safety because we would have to cast. Now it's sort of we took responsibility, for knowing about the types of things as opposed to, this taking responsibility and taking that off of our plate. So we can express arrays this way too we've been expressing arrays until now using some type and then square brackets, so now I'm showing you we can pass it into, a type parameter of the capital A array type.

[00:03:15] So this would be an array of 52 undefined's but the type of that array is that tuple there, just like a card dealing exercise. Promises, we can pass a promise a generic parameter. And that will be the type of value that that promise resolves to, which is really, really nice.

[00:03:35] If you've been working with promises for a while, it's most JavaScript building web applications to do, you kinda lose a lot of information about what this promise is all about. And especially with functions that take arguments as Promises
>> Mike North: You need some context and you basically need to trace backwards, like, where did this come from?

[00:03:55] What were you asking for? What can I expect as a response? Is there a fetch somewhere inside that? Then it's probably a response you're gonna get. So now we have type safety around promises, not just about it being a promise but it resolving to something reasonable. Finally tomorrow, when we dig into react components we can take in two template parameters, one which represents props and one which represents state.

[00:04:22] So props are the things that you can pass a reactive component as attributes almost like HTML attributes. State is sort of the internal things that have to be tracked by that component in order for it to operate normally. So that might be like if it's an accordion you know whether it's open or closed, that could be considered the state.

[00:04:47] The benefit here is if you then, add something to the react component if you pass something in that was not listed as one of the props, that you should be passing to the component or say you misspell it, type descriptor will catch you. Or if that component, if you say okay, well we're gonna enhance this and now I need this value and you add that to props.

[00:05:10] Now you're gonna get problems showing up in your problems tab, there will say, okay, well, all these consumers of this component, now you must give me something for that. You are no longer given me an object that I can assign to this prop’s interface, right? It is not of correct type, and so now you have a list of things to do.

[00:05:29] As opposed to, what are the alternatives?, like a git grab through your code base and try to do it the way we were doing it in 1992, this is a better way.
>> Mike North: In addition to just taking in a type parameter t, you can describe a constraint on a generic.

[00:05:54] So this would take any type that can be assigned to, or that is at least structure of point two d. So this would be able to, for example, depending on the implementation of this algorithm here, you could say, look, I will calculate the mid point of two, two dimensional points or two, three dimensional points.

[00:06:15] Or if you can find a way to represent time as a number in this point things, something where I can treat at the same way as I treat distance. I can even do like a four dimensional point, space and time and find like the midpoint of your flight from one place at one time to another place at another time.

[00:06:37] And you would get back the correct type, you would not get just a Point2D back, you would not get an any back. You get back something that represents the same thing that you put in, right? But this type constraint here, what you're doing here is you're saying first of don't just give me any type, don't give me a string, I want a Point 2D at least.

[00:06:57] And then from within this function, you're gonna get on, as far as properties you'll allowed to access at p1 and p2, you will be able to refer to things that are at least what point2D has. Right, as long as you can do whatever work you need to do.

[00:07:13] Say there's like a property on there called chords and for points in higher dimensions you might have more numbers in that array. It is possible that you have the information you need and you can return the appropriate type. There are even ways that you can instantiate a new object of type T providing that part of the Point2D interface is a constructor.

[00:07:42]
>> Mike North: And then down low, you can see we can use it with an interface as well. So we've used it with a function and with an interface and this interface basically says to be a file reader, you must have a function. So file reader is expressed in terms of a file type and say T extends File, so we might have like JPEGFile.

[00:08:02] Right, so if you implemented the interface IFileReader and then pass in JPEGFile as the template parameter there, now you must have a function that takes a single argument which is a JPEGFile type and it returns a blob. So this is, is sort of one more layer of abstraction out and you can take multiple template parameters, if you wish.

[00:08:26] You just need to separate them by commas, before you close the angle brackets.