Ensure Valid Types with an Assertion Function
Let's work out the solution together.
We started with assertUserIsAdmin
:
function assertUserIsAdmin(user: NormalUser | AdminUser) { if (user.role !== "admin") { throw new Error("Not an admin user"); }}
Trying a Type Predicate
If this was a normal type predicate, t
Transcript
0:00 Let's figure this out. We have an assertUserIsAdmin here. If this was a normal type predicates, then we would think of it is isUserAdmin, and then we could say user is AdminUser.
0:18 This is OK, but the issue is here, then we would have to go, instead of throwing the error here, we would have to return user.role === "admin". That means that we need to change a little bit of our code down here to say, if -- what's it called now -- (isUserAdmin).
0:38 Then what we do, (isUserAdmin(user)). Inside there, then this test would then pass, because this user now, if I actually...Oh my gosh. There we go. This type of user now, which is have a look at user is it's going to be a type of AdminUser. This type predicate means that inside the scope where you check it, then it's going to be what you think it's going to be.
1:04 How do we do this other type, this asserts thing? Well, we can use an assertion function in TypeScript. I'm going to say, if (user.role = "admin"), and we're throwing this error here. We're not returning anything from this, but what we are doing is we can throw this asserts keyword in front of it. Now we've got asserts user is AdminUser.
1:27 Oops, I need to change the name back here. Now in this case, all we need to do is call this function on something and it will modify the type of it. What we get is assertUserIsAdmin, this user, and then user. If we look at it, it is an AdminUser. Just by calling a function on that thing, not returning anything from it, we have changed the type of it. We've modified the type of it.
1:55 This is about as safe as a type predicate. We can do asserts user is NormalUser here. This is getting it wrong. Now, we end up with this. We're now asserting that the user is a normal user. You've got to be careful with these types of assignations here, but it does work surprisingly well.
2:18 It means that we can do some clever stuff here, which we'll look at later in this section. I want you to be thinking about this. If you ever find yourself writing these checks, especially if you're checking if things are valid or checking if things are assignable to other things, or even like a test framework, this is super useful too.
2:38 Assertion functions have a lot of use cases in more advanced TypeScript. I'll show you that in this section.