
Lesson Description
The "Type Assertions" Lesson is part of the full, TypeScript: From First Steps to Professional course featured in this preview video. Here's what you'd learn in this lesson:
Anjana explains the concept of type assertions, where developers can override TypeScript's type inference by explicitly specifying the type of a value using the "as" keyword. Anjana demonstrates how type assertions can be used to inform TypeScript about the expected types in situations where it may not be able to infer them accurately.
Transcript from the "Type Assertions" Lesson
[00:00:00]
>> Anjana Vakil: Now, we're starting to get into a situation where we have some things like this event, where if I wanted to give it an event type, I can't, because this isn't a function definition or a variable declaration This is a value that I am passing in as an argument to a function So TypeScript syntax does not work here And even if it did, or like if I, where I would want to type this variable, would probably be here where I declare it
[00:00:37]
And yet this will not work It says type unknown is not assignable to type event Why does it think it's unknown Well, because that's what better-sqlite3's types said that this could return Now, this is out of scope We're not talking about how to interact with a SQLite database at all in this course, but the idea being if I have a database, the database doesn't know what kind of stuff I'm putting in it
[00:01:14]
So it would be pretty spooky if the developers of that tool somehow could predict that years in the future or whatever, I would be wanting exactly an event to come out of this get method There's no way they could know that And there's no way TypeScript could know that then So this unfortunately won't work Now, this is where, again, we sometimes know better than TypeScript does
[00:01:50]
We have a way just like we had a way to tell the compiler to ignore things, tell it to not worry about checking types on a line or use any explicitly, what have you We also have a way to tell TypeScript that we know better than it does what kind of thing something's going to be So for example, document.getElementById doesn't know if there's actually going to be an element there
[00:02:28]
It could be null And if there is an element there, since we're getting it by the ID, it's not like we're doing a query selector over the button element So I could put up my button ID on anything It doesn't have to be a button But let's say that I know that in my page where I'm running this or whatever's happening, this exists, a button element with the ID my button is there, and it's not going to be null, and it's not going to be a form element or a P element or some other element
[00:03:14]
Why can I not think of anything in the browser right now But anyway, it is something that we're like TypeScript, I swear to you, this thing is going to come back with an element and that element is going to be a button I swear it exists and I really need you to believe me And so what we have is a way to explicitly tell TypeScript to understand this value—oh, and I renamed it, so, OK, imagine those have the same name—that it's going to have a particular type
[00:03:57]
TypeScript would not be able to infer or even believe me and it would be like it could be null, it could be whatever, it could be a form, it could be a file, it could be blah But if I use an as type, what I'm doing is it's called a type assertion, but we can also—it's not exactly like casting because casting is something that JavaScript does at runtime when it's like, I see a number, and now I have a number, but I'm going to make it into a string so I can put it into your string template and render it for your users undefined or whatever
[00:04:38]
And so what we're doing is we're not actually changing the value because it's TypeScript We're not running the code There are no values yet Instead, what we're saying is we are saying, TypeScript, I swear to you, and I'm forcing you to believe me that this is the thing, this is the type that I want you to understand this value as
[00:05:03]
I guess that's why they called it as The keyword, if I didn't have this as here, again, TypeScript knows what a document is, it knows what the getElementById method is, it knows what kind of stuff it returns, and it knows that it always returns an HTML element, huge wide type, or null And so that means that that is also the type that I swear this button exists gets
[00:05:36]
But once I assert that this will be interpreted by the compiler as a, will be understood by the compiler as an HTML button element Sure enough, now TypeScript's like, OK, you swore to me, so I'm going to believe you And now, anywhere else in my code, this is going to get treated as an HTML button element and not could be null, you know, might be an HTML form element or whatever else
[00:06:14]
So, what we can do in cases where, for example, we have something coming back from our database, and better-sqlite3 doesn't know what stuff we have in our database TypeScript doesn't know what stuff we have in our database I, the developer, know what kind of stuff we intend to have in my database I can say, hey, OK, whatever's coming back from this by ID get is going to be an event, sorry
[00:06:57]
An event where, hopefully we imported it, yes, OK And so this is now giving us this event type where before we had stuff like unknown because the return type of blah blah blah, all this database stuff here was like a bunch of unknowns We don't know what kind of things we're going to get from it So here is an example of where I can tell TypeScript I just, you know what, I know better
[00:07:32]
Just do this, just understand that this is an event And so then it stops complaining to me about things like unknown is not assignable to a parameter of type event, because I had said that join host takes in an event and returns an event with the host being something, don't know yet We are now able to, oh, sorry, wrong line
[00:08:10]
Now able to satisfy the TypeScript compiler that it is getting an event as the argument passed in to this function So this is what's known as type assertions, and it does have something kind of a similar vibe to casting types, like toString or something like that But again, it's a TypeScript concept, no values are involved, no values were harmed in the making of these types
[00:08:41]
And it is one of the cases where I am overriding TypeScript inference and TypeScript understanding of my codebase And so similarly, if I have this event coming back as like an unknown array, I might want to say it's not unknown, it's an event And now, I believe, since we have the built-in type event, it's not helping me out with my autocomplete
[00:09:23]
But let's type it out And now it's saying I think that this is super wrong because this looks—uh, OK, no, we did have our event here imported Great, fabulous And so it's saying this is not going to be a very helpful conversion here from this unknown type that is a stand-in for a type we don't know yet to an event type because we're starting out with an unknown array, and we're trying to convert it to type event
[00:10:02]
And so even though I'm saying, hey, TypeScript, listen to me I typed an as and then I typed type and I am a developer and I am smarter than you It's going to be like, are you Because this might be wrong And sure enough, I probably did something wrong here Any thoughts Event array Exactly An event array is much more similar to an unknown array, so now, TypeScript is happier
[00:10:39]
And there is a way to like super overwrite it, but we're not going to talk about it because we should never do it So now, we're going to see that we have one of our squiggles down, because it knows that events is now going to be an array of events, and similarly that we saw before when we're mapping over stuff, it knows that then that's going to get in a single event
[00:11:14]
What it does not know is that there's something unclear happening here, and we see that in its understanding of how our event type looks, it has something like an unknown array of RSVPs So something interesting is happening here Let us take a look at this join RSVPs I can go to definition and see what's happening here And sure enough, I had typed the function parameter a type, so I know what type I can expect coming in
[00:11:56]
But I didn't exactly tell it what this RSVPs array is going to be And so this RSVPs array, which is coming from this get RSVPs.org, similarly we had like get events, what have you, it's also an unknown array So maybe if we tell it what kind of an array it's going to be, TypeScript will be happier with me So I can do as and start typing my RSVP array
[00:12:31]
It's just that it doesn't know what that is because I haven't imported it yet So let me add it here, RSVP, did we not Oh, it doesn't know what it is because I didn't ever export it So that's why it couldn't helpfully autocomplete for me because I'm such a clever developer and I know better than TypeScript So let's go back to our types.ts
[00:12:59]
Let's add one more export here Oh, now look at this, now we've got a lot of types that we can work with through the rest of our codebase And so back in events.ts, it now knows what an RSVP is, it now knows what an RSVP array is It now knows that RSVPs is going to be an RSVP array, and it now knows that the return type of this function is going to be objects that look like the event object and have an RSVPs array tacked on
[00:13:42]
Let's say, and all of that is coming from the inference of how these functions are written And so then later when I call or when I pass in join RSVPs to my map function, it's no longer complaining about RSVPs is an unknown array Instead, it's saying that the problem is that the join host function, similarly, it joined the host, but the host, if we look in the hovered type, the host is also unknown
[00:14:38]
So similarly, we need to go and find our join host function and we can do another—host is going to be a user, so we can do another as user It does not know what it is because we didn't import it yet, but I exported it, so VS Code knows that it's there and I can click that or press tab if I were writing it out, what have you
[00:15:06]
And now I have this user, I can assert or convert this whatever's returned by get user to a user, and now this function returns host user instead of host unknown on its type, and so our map now understands that there's going to be a user as the host, an RSVP array as the RSVPs, and that all of that stuff is going to work out
[00:15:42]
And now similarly, we have sort of a smaller situation here where we have an ID that's coming back from, this is like a SQL thing where it's like inserting some stuff and we're getting back our ID and it could be a big int because we could have a lot of stuff But we can let TypeScript know that we want this to be, no, sorry, not there
[00:16:24]
We can let TypeScript know that we want this to be a number Perhaps by instead of renaming the variable all at once, we can do const ID equals lastInsertRowID which is indeed a number or bigint, as a number And so I needed to add a little bit of indirection here just to get the syntax working But what we've got is now something that could be a number or a big int that TypeScript is now satisfied is only going to be a number
[00:17:00]
The thing is, that may or may not be true So when we do these type assertions with this as, we're playing a bit with fire here because again this depends on me knowing better than TypeScript and just like any or ts-ignore that may or may not be a good thing for me to override TypeScript and say, here's what we're going to do
[00:17:31]
OK We have a couple more things to type here, but it's same same, so I think we can consider ourselves even more, even more well equipped to break our code by overwriting TypeScript with another little keyword as And the thing is, same with any, same as as ts-ignore If we're using as we are living dangerously We're living on the edge
[00:00:00]
Austin Powers might like that, JavaScript might like that, but might not always be the best idea, so be very careful when using these kind of like, I know better than you TypeScript things.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops