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

Mike introduces constraints and scope within the context of generics.

Get Unlimited Access Now

Transcript from the "Constraints & Scope" Lesson

[00:00:00]
>> Mike North: Type parameters can also have constraints. So, as you'll start using type parameters, you'll see that if you don't have a constraint like this, this is the constraint part. This is saying T must extend, must be assignable to, this type here. The best way I can explain constraints to you is to remove this to reveal the motivation for adding it.

[00:00:29] And there you go. So, we're getting a type error because we're trying to transform an array of type T to a dictionary of type T. And we begin by creating an empty dictionary, we iterate over the array, we try to place each value into the dictionary, but it turns out we can't access this property ID off of each member of our array.

[00:00:56] And the reason is we have not declared that there is a minimum requirement that T must meet, and as a result, there's very little that we can do with values of type T inside the function. It's really flexible in terms of what can be passed into the function, but you can only do the things that you've explicitly asked for.

[00:01:18] If we need to access ID, we must state that T must be an object and it must have a property called ID, and this is how we would do it. We accept a type T, that is at least an object with a property ID whose value is a string.

[00:01:37] And now, this would be a string. So, this is the equivalent of doing something like this, that we could try to remove this and just say, I'm taking an array,
>> Mike North: Of objects that look like this. And we could try to change this.
>> Mike North: Right, instead of T there, we can replace the T here.

[00:02:06] We're gonna run into another problem. So, I've basically boiled this down to my minimum requirements. I've said transform this array to a dictionary, but there's no type parameter any more. Here's the problem we'll run into. Number one, we're getting errors for passing in any properties that are more than simply having an ID who's value is a string.

[00:02:34] The other problem we'll get is,
>> Mike North: When we try to access things off of it, we've greatly simplified this type in a bad way, right? We've lost any of this extra stuff that was passed in. What we want is to be able to pass in anything that has an ID that's a string, and to get out a rearrangement of this from an array to a dictionary.

[00:03:00] But we haven't lost any fidelity in the types, we still have access to everything we put in. And that's where we're gonna say, all right whatever you give me an array of type T, I'm gonna give you a dictionary of type T out, right? You'll still be working with whatever you pass in, you'll still get it back in dictionary form.

[00:03:21] I'm not gonna reduce it down to just objects that have ID, you'll have it as you gave it to me. And then the type constraint, we already went over. This is the equivalent of saying, look, I'm not just gonna take, it's a way of stating your requirements for working with this type within the function.

[00:03:46]
>> Mike North: And why isn't everything happy? I forgot one last thing. Now we're good.
>> Mike North: So just to recap, by making this abstract, by adding this idea of a generic,
>> Mike North: We can,
>> Mike North: Retain the detail of the object we passed in even though this function that was doing the work, it knows nothing about these extra properties that might be there.

[00:04:22] But because it's given us a blank that we can fill in, from the outside we can say, for the purposes of invoking this function right now, I'm giving you huge objects with lots of properties in an ID, and you'll get those same types back, you won't have to deal with sort of the lowest common denominator, cuz that puts you in a position where you sort of have to like figure out a way to widen your types again to make this more useful.

[00:04:56]
>> Mike North: Like function arguments, type parameters are associated with a scope. So here we have a function that returns a function, start tuple, finish tuple, right? And we're using a technique that Kyle Simpson in his Frontend Masters course on functional light programming. He calls this zero point programming because we're returning a function and then invoking the function that it returns immediately.

[00:05:26] So we pass in one argument, an array of strings, a second argument, a number, and the type of the tuple we get out is this. So just like A and B, right? The values, those are regular function parameters, in here we can access both A and B. And because of this analogy where generics are like functions, we can also access U and T.

[00:05:55] Now out here on line 94, could we access B?
>> Mike North: No, and we can't access U either, they are associated with scopes in the same way. And this fits similarly to having a type parameter on a class and then on a method within that class, right? Outer and inner scope.

[00:06:19] You could have a class, a method within the class, a function that that returns, it works just as you'd expect cuz I've found this to be a very effective analogy.