Production-Grade TypeScript strict In-Depth
Transcript from the "strict In-Depth" Lesson
>> So now we're finished with my like standard boilerplate TypeScript Project Setup. And I want to spend a moment looking at the notes section five. I want to spend a moment talking about what we've just done in a little bit more detail. So, also note that I the latest code has been pushed to this little repo.
[00:00:28] And so, you can take a look at that as we discuss a few things and I want you to understand what we're looking at here. My hope is that this is a simple enough setup that you can really have a grasp around what's going on. So we talked already about our tsconfig, and what exactly strict means.
[00:00:52] In the notes, I have a link here. To the source of truth in the TypeScript project itself, where you can look and see which of the various compiler options are included with strict mode. So you can see for yourself there, don't take my word for it. That's where that information is located and as the project evolves unless they move that somewhere else, I will update the link if we if we have to.
[00:01:18] But that's where you can see exactly what strict means because it's not just things that begin with strict. No implicit any. So that's one of the things that's included with strict, this effectively means In the absence of the ability to infer the type of something, we default to asking the code author to tell us something, right.
[00:01:48] So if we have like a function that takes an argument, subtract is a great example here. I don't say what b is. It implicitly has an any type. There's no way to know what b is. No way. I mean, if in some languages you could go down to line 10 and see this is minus operator, and so we could reverse flow up into the function signature and understand that this is the spin number.
[00:02:17] TypeScript doesn't work that way. Typed information only flows in one direction and if for example, I did this could be string concatenation, right? Not every operator it's like a smoking gun in terms of a clue to what type something is. So if implicit anywhere allowed, this would be fun, but here if I really wanted any, I have to be explicit about it.
[00:03:03] So let's look at this. So let's say we have a button Actually I can just do this. So, we'll talk about what declare beans later snow for now it gets rid of that error message. So if I did lm add event listener, click and then I follow up with a function So, can somebody in the class tell me if I if I do this, what might I see when this button is clicked?
[00:03:53] What is this on line 16? What am I gonna see there? Anyone have an idea? I'll give you a clue.
>> I've seen the elements.
>> It is the element. Yeah, I've chosen this example for a reason, right? It's a very specific example, so it's relevant here.
[00:04:11] Yeah, it's the element. So I could do like this class name. Hey, there it is. And in fact, TypeScript knows about it. It knows that this is an HTML button element. So, when defining this callback here, it has to say, you must pass me a function whose this is the right thing.
[00:04:38] Because if I were in here, say it was a method I pulled off of something, something that's already bound, this will no longer be that element. So that is what strict or no implicit this is all about. It means that if you rely on this being something special for a free standing function, you must state so.
[00:05:41] There was sort of a much looser mode that this was allowed to operate on and like so, enabling strict bind called ply, sets the types of those three methods on the function prototype to exactly what you would hope they would be, where the arguments passed to the function are validated.
[00:06:01] Right. So here if I were to say, subtract bind, so we'll say, undefined. And now, you can see that I'm being asked for a number, our zero has to be a number. Or I could pass in two numbers. Well, now I'm seeing the generic implementations here, but I could do three and four and it would be fine.
[00:06:23] But if I did this Interesting, it's still letting me do it. Because I have an error here. It's letting me do it because I've been bad. Yeah, so this is exactly what you'd want, right? You want that validation, you want the signature of subtract to be taken into account with bind, because this would be nonsense to pass the string four like you're just asking for trouble there.
[00:06:52] So that's fine call plays strict null checks. So this option is all about making sure that no values are their own type. With strict null checks, disabled, you know isn't allowed value in any type, numbers can be a number or null. Strings can be a string or null.
[00:07:20] And this is a big problem because we often rely on type narrowing like we had declare const as string or null. So if this were our string We want to be able to narrow things down this way, and of course you have an empty string to worry about.
[00:07:51] But if Knowles can be found anywhere, you're really gonna find yourself in trouble. Like, what's gonna happen here? So strict null checks would would like it would allow something like this. This could be null, so you're asking for runtime errors here. If anything has the possibility of null, if anything has the possibility of being null, you're exposing yourself to a whole class of problems where you're just gonna see like, cannot call function blah, blah, blah, unknown.
[00:08:27] You don't that, you want like that is easily solvable at compile time, so you want that to happen. Strict function types. I'll let you look mostly at the example in the docs because it's a little bit nuanced, but just understand at a high level, that when if you're holding, let's say you have a callback, you store that in a variable like a function stored on a variable.
[00:08:50] You wanna make sure that the types of the arguments that can be passed to the function are validated as part of comparing the type of function one to function two. And then strict property initialization, we've already dealt with that today, that's making sure that if you have class fields, they have to be initialized either with field initializers or in the constructor.
[00:09:14] That's, that.