Check out a free preview of the full TypeScript 5+ Fundamentals, v4 course
The "this Types" Lesson is part of the full, TypeScript 5+ Fundamentals, v4 course featured in this preview video. Here's what you'd learn in this lesson:
Mike discusses how "this" refers to the context in which a function is called, such as the DOM element that fired an event. Explicitly providing a specific "this" type to a function using the bind method, and how to invoke the function with the correct "this" context is also covered in this segment.
Transcript from the "this Types" Lesson
[00:00:00]
>> All right, part of functions is the concept of this, right? So if anyone's written something like a mouse click handler or a DOM event handler, you know that sometimes, like if you hook things up the vanilla JavaScript way with addEventListener in a browser, this will be the DOM element that fired the event.
[00:00:26]
So if we wanted to have a click handler like this and pass it a click event, we wanted to rely on this being something, like this being something, we need to provide it with a type. So here's a more involved example here. So here we're getting a button.
[00:00:51]
We're literally getting the first button in a document, like in an HTML page. We can create a boundHandler that tries to take myButton and bind its context to undefined. Well, let's sort this top piece out first. So what we're seeing here is that this cannot be depended on unless we provide it a specific thing.
[00:01:24]
So what we'll wanna do is the following. All right, it kind of looks like an argument. You might look at this and say, have we just made a two-argument function? But it disappears. This is still a one-argument function. We're sort of using the arguments list as a place to put a type for this, but note, now we get the correct type here.
[00:01:54]
So if you ever want to build functions that need a this to be a particular thing outside the context of class methods where it's handled for you behind the scenes, this is what you'll need to do. Note that if we just tried to invoke myClickHandler and pass it an event, this is not going to work.
[00:02:16]
We don't have the correct this type. It says this context of type void, there's void again, it's like, don't use this, ignore it, you shouldn't be sensitive to this, right? That's what void means here. It's telling us this is not safe, you shouldn't do this, you can't do this, because you need to create the proper type.
[00:02:37]
So what we're doing here is we're creating a button. We're then saying, I want to create a copy of myClickHandler and I want to bind it to my button. Does everyone in here knows what bind is? So you're almost creating a copy of this function that's sort of packaged with a this applied to it, and now anybody can invoke this without worrying about what to set this to, it's just ready to go.
[00:03:13]
So now we've created this new function here. boundHandler is of type any. This is a good little segue here. We're gonna need to go to, you can do this with me here. We're gonna need to go to the package.json. No, not the package.json, the tsconfig of this notes project.
[00:03:35]
So it's in the ts-fundamentals-v4 folder, get the tsconfig. So we've got no implicit this. That's why it was lighting up here before we added a type for this. And now we're gonna add strict, bind, call, apply. Set it to true. And look at that. So strict, bind, call, apply.
[00:04:03]
This used to be any, but now it's of a particular type. And if we look at the type of the click handler to begin with, see this piece? And now when we have the boundHandler, we've sort of taken the requirement for explicitly providing a this a way as part of what bind does.
[00:04:25]
So it's giving us a bound version of the function. Now that lets us just directly invoke this function. This is already sort of glued to the boundHandler copy of the function. Alternatively, we could invoke the original function, which still has a this type in it, and we could call it, but we have to pass it this button as the this.
[00:04:56]
These are sort of like meta function methods, a way to invoke a function a different way. So if we were to open this up, you can see it's like, it's demanding that we provide an HTML button element, cuz that's what we need here. So it's only happy if we put in myButton.
[00:05:25]
It's kind of rare to deal with this types. If you're using them in a class, great. Where it becomes particularly important is listening to DOM events, that's the most frequent case. Or if you're building React components and you're kind of mixing top-level functions with methods, that's where depending on which of those two you're choosing.
[00:05:50]
One, the top-level scope freestanding functions should not care about this. Methods already have the instance of the class as this.
>> So could you still call the function on line 82 and pass our first argument?
>> You can't. When you invoke a function in this fashion, I'm trying to not use the word this in my explanations, desperately, you don't get to explicitly provide a this.
[00:06:23]
This .call, that's what you need. This is the way you would do this. Or function.apply is another way of doing it. Apply, call, and bind are kind of ways to sort of. Apply and call are ways to invoke the function and pass it arguments, but also a this.
[00:06:42]
Bind is the one that sort of bakes a this in to a copy of the function and gives you that copy which, at that point can be directly invoked, just like you see here. Yes, sir?
>> Is there something specific happening with the word this, if you change that first argument to just element?
[00:07:02]
>> Very special.
>> Okay.
>> This is a special Javascript concept.
>> Okay.
>> Not something TypeScript invented.
>> Okay, but if you name that first argument just element, you could still say element.disabled = true, right?
>> Yep, but that would require that you explicitly pass it in.
[00:07:20]
>> Every time, yeah.
>> So you could do it like this. This is why you don't see it so frequently cuz this is wiser. And if we were to just move, select down, out of the temporal dead zone. There you go. So it's almost like an implicit argument.
[00:07:42]
This is why if you're making a freestanding function, you wanna do it that way. Now, if you're attaching an event listener to a DOM element, you don't really have a choice there. You can't tell a DOM element how to invoke your function. It has defined the way it invokes your function, and it will set a this.
[00:08:07]
And if you want to write a TypeScript function that can take advantage of this, you will need to provide a this type.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops