The Utils Folder 10 exercises
solution

Add Constraints to Generic Functions with the extends Keyword

We are going to learn how to add constraints to the parameters of a generic function. We'll begin with the function, addCodeToError, which uses the generic type parameter TError:

The syntax to add constraints is the same as what we saw for generic types.

We need to use the extends keyword t

Loading solution

Transcript

00:00 Okay, this syntax for this is exactly the same as what we saw in generic types. So we have TError here, and we're going to say TError extends, and we're going to start with message string. Now what this does immediately is it forces us to make sure that the thing we're passing in

00:19 essentially has a message string on it. So we're getting an error down here, this TSExpectError is sort of slightly in the wrong place for this error, whereas it's saying object literal may only specify known properties, code does not exist in type message string. It's basically saying, sure, you're not passing in a message, basically. You should be passing in a message into this slot.

00:38 And so if we get message here, now the error goes away. Beautiful stuff. So it's forcing us to put a message in the object that we're passing in. But what about the error inside this function, error.code? Okay, so we know that error must have a message, and if we access error.message in here, it's being typed as string

00:57 because anything we pass in must have a message in there. Great. But what about the code? Well, let's add code to it. So now, code, it's, as we said in the intro, it might have a code, the thing we passed in, so we're going to make this optional. So now we get code could be a number here.

01:16 And now we can access error.code, and it's number or undefined, and if we don't have that, then we default it to the unknown code. Brilliant. So now, if we hover over this add code to error, you can see that it's error being inferred as the type argument because that's the thing we're passing in, passing in a new error.

01:33 If we pass in a custom error with an extra property, like a file path, then we get that back too, so we get message, code, and file path. So what you'll notice is that, sure, we're constraining it to be a certain type, but you can actually pass in other types too. So you can pass in excess properties in there, and it will remember all of those.

01:52 So we're basically saying, sure, this must have a message, it might have a code, but you can pass in anything extra you want to. This means that whatever error we pass in here, we will get the same thing back just with a code added on there. And so we'll get all the autocomplete that we're used to here.

02:10 Whereas if this wasn't a generic function, if this was just like a, sure, it just returned an error and a code added to it, then we wouldn't preserve things like the file path that are being passed in initially. So this is how you can add constraints to a generic function to make it more specific to the kind of things you want to pass in.

02:30 It doesn't mean you can only pass in these properties, it just means that you're constrained to this shape at a minimum. You must pass in a message, and you can optionally pass in a code, and other stuff that's passed in will be remembered also. Really, really useful.