Check out a free preview of the full React and TypeScript, v2 course
The "Typing Components Exercise" Lesson is part of the full, React and TypeScript, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Students are instructed to refactor the controls.jsx component to use Typescript. When to use types versus interfaces is also discussed in this lesson.
Transcript from the "Typing Components Exercise" Lesson
[00:00:00]
>> All right, so your mission is to take that control, that JSX, do the very hard work of flipping it, that J to a T, right? And then what we wanna do is refactor those prop types into an actual prop and just kind of get warmed up and get into it.
[00:00:19]
Like I said, for stuff that might not be totally obvious, try not to look at the docs. See if you can do it from just hovering over the editor and use the actual tools to figure out how to use the tools. It's like building your own lightsaber, right?
[00:00:39]
Guys, we're changing the file extension from JSX to TSX. We're gonna take those control panel props and turn them into actual TypeScript types. We might go for a bonus run and just add another property so we can play around with it a little bit on our name badge.
[00:00:58]
And then we're gonna try to figure out what to do with at least the on change handler, right? Cuz I told you, hey, just say it's a string for the name, I didn't really tell you what to do with events. So that was, a little vision quest for you to kind of look through, but we'll kind of figure out how to use the editor to figure that out.
[00:01:14]
Okay, so we have some of the answers down here. Step one, you can either change the editor or you can get move, you want your get history to be nicer. I'll just do it in here for right now. And so okay, I changed the TSX. I'm getting, everything mostly works except for the fact that it didn't acquiesce to these prop types were real types.
[00:01:37]
So the convention, and I like conventions cuz I don't wanna come up with my own, right? And also, one of the hard problems in computer science is naming things. So what you will normally see, what is, I don't know who made this rule, but the standard convention is you can type it in line or you can make a new type, which is what we're gonna do.
[00:01:59]
And a lot of times for React components, you would call it ControlPanelProps. And that would be the type of the props, you would pass to the control panel, right? And we'll start out by saying that we know that name is a string and let's just say that on change for a hot minute is any.
[00:02:21]
Now, one of the things I wanna say early now which is, if you ever feel tempted to use any, you should avoid that. Any is infectious, one you have one any, anything that any touches basically becomes any and now you have signed up for a life where you do most of the work of having TypeScript in your React app and get only 60% of the benefits.
[00:02:49]
So as soon as an any is entering, it just everything an any touches turns to an any. So we'll do that for a minute, there'll be, I'll like sneak a few anys in there, to set up exercises and we'll try to eradicate them over our time together. So we'll save that.
[00:03:05]
And then all I have to do at this point, if you didn't like that set of curly braces in the other one, you just do ControlPanel props. And this is now officially a TypeScript component. It has some extra stuff I don't need, like this doesn't do anyone any favors anymore, which means I don't need this.
[00:03:25]
And that, for a very simple component, which if you think about your app, it's a few complicated pieces and then the way the satellites are around the earth, a satellite of smaller pieces, right? We can have this kind of in place, which leads us to our next challenge, which is what do we do about OnChange here?
[00:03:45]
So my challenge to you, yeah, [INAUDIBLE].
>> Can I answer?
>> Sure.
>> Change event handler HTML input element.
>> Let's hover over that. And yeah, we can see that the default type of an onChange. So, what do we do about our onChange? Well, we look over reacted to the default element and we steal that, right?
[00:04:07]
So it's saying like, an input elements onChange is this type, React change event handler on an HTML input element or undefined. Yoink, copy, Paste. Boom, right? We just used our editor to figure out what the type should be on that one, right? And so a lot of times if I'm like, I don't know what a form should be, you can mostly kind of, I'll make the element and I'll figure it out, Mark.
[00:04:37]
>> Is there a reason why we are using type over interface here? Is it a different use case?
>> Yes, I am spiritually prepared for this question. One moment, please. So, the question was, why are we using type instead of interface? And so, a while back there was a lot more of a difference between a type and an interface.
[00:05:03]
In modern versions of TypeScript, there are less differences between types and interfaces. An interface is kind of like a class where you can extend it and kind of override individual properties. A type is a little bit more constrained, but you can kind of use it with what we'll see later are like generics or type variables.
[00:05:25]
A little bit easier when you're combining stuff together. If one were to Google this, you would find probably, I would say 80% of this advice saying that for public facing things where you want someone to be able to extend it, to be able to pull it forward using interfaces for public libraries, but for internal stuff using types.
[00:05:51]
You will also find some arguing the opposite. It doesn't matter so much. Generally speaking, my heuristic then given the private public kind of peace and extending versus using unions and intersections, which we'll see in a little bit. I tend to use types unless I explicitly need an interface.
[00:06:10]
There's little places where combining two types that have an overriding property where it can become a little tricky and then I'll grab for an interface. But my heuristic is to use types. However, if I were to go to somebody else, join a new team, and in their application they're using interfaces everywhere, you know what I start using?
[00:06:33]
Interfaces, right? Yeah.
>> Sorry, what exactly is an interface?
>> So interface, if I wanted to change this type from a type to an interface, I would change this word to interface. I would get rid of that equal sign, no red squigglies, right? The difference is if I wanted to, I can say interface, ForAdminsOnly, I can do this extends.
[00:07:09]
>> It's kind of a class.
>> Yeah, and I could say, it's always got all the other properties but I could also say like, Right, so now this has name which is a string on change with an event handler and is admin has to be set to true, right?
[00:07:28]
If I wanted to do this with types, it would be like, That, right? So, they both get me the same effect. It's usually when these have overlapping properties or stuff like that, stuff is a little bit different in the actual implementations. But generally speaking, these will do functionally the same thing.
[00:08:01]
So my rule of thumb, so the question was. Do I always leave them in this file, or do I put them into a globally available definition file. The answer to that question that either or question is yes. Generally speaking, I cuz if I put them into a data ts file, I think I have an empty one sitting over here.
[00:08:27]
Any types that I put into this file and later examples will have stuff in here. Mostly cuz I don't wanna clutter stuff up, but in a larger app, I will usually put the very commonly used models. So the thing I work on has workflows and workflows have events, and those are used all over the place.
[00:08:44]
It's the whatever they're the core things that your app is showing. If was Twitter tweets, those types that I'm using everywhere. I don't want to import those constantly, so I will move them into this file. That said, I personally and this is definitely a subjective opinion thing. Tend to start them out in the file, cuz, I don't need to be littering the global namespace.
[00:09:09]
With all these types that are only ever actually getting used in one file. So, normally a lot of my types will start out in a file, and when I find myself getting very annoyed importing them places. I will begin to break them out, and move them into definition file, so, it's usually a refactor for me at some point.
[00:09:26]
>> Excuse me, I also have one more. If I recall correctly, another difference between interface and type is that for typed you can or the types when you pass it in. So especially if it's helpful in Redux, I believe. I don't think you can do that with interfaces.
[00:09:42]
>> Yeah, I don't think so, it's one of those things where since I predominantly use types of specially for that. For primitives I wouldn't straight I think about for very simple things. Like a type makes total sense because you can say this one or that one. There's really interesting things you do with unions.
[00:09:57]
It's like they are, they have an overlap about 60 or 80%. There's a chart that I have a broken link to, that'll fix. That shows most of the check boxes are green on both of them with one or two smaller edge cases across both. I think the more important thing is consistency in your code base.
[00:10:16]
I choose to use types, but like I said, they have certain limitations. And some edge cases interfaces are gonna have certain limitations and the other one. But I think consistency is probably the answer but there is not necessarily. Like this is right and this is wrong despite what blog posts on the internet will tell you.
[00:10:35]
I have been in code bases since I do both. Okay, so we've got on change handled. Again, if I needed to know what a form element was, look, it's a form event handler. There are a bunch of these, I have a link in the notes slide we can just see all of them.
[00:10:54]
But generally speaking, I do wanna encourage you, rather than looking at the list to kind of our habit is going to be learning through doing. Learning through getting hints from our editor. But these are basically just if you like Command click you can eventually get to the definition and kind of see everything I like.
[00:11:13]
Obviously the types for reactor obviously complex. But you can kind of go through and see that they're all kind of going over the regular dom events. Cuz events have different properties, only ones based on input elements have a value on the event target and stuff along those lines.
[00:11:32]
So it's basically trying to figure out what you have on that event and what you don't. Cuz not all events in the DOM are created equal, some of them have different properties. Like mouse moves have the mouse position, while form submits have the target of the form. So it basically fills in all those for you.
[00:11:49]
So generally speaking, if I don't know if I need to use an element, I need something that will match that. I will usually just even create that element hover over and steal the answer is a lot of times a lot easier for me. Than stopping when I'm doing pulling up Safari because I will get distracted and I will look at guitars.
[00:12:08]
So this is a lot of times easier to kind of keep that train of thought and focus in there. Yeah.
>> So for my on change I assumed it was a function. I just did the open and close parenthesis and arrow function to void and that seemed to work.
[00:12:25]
>> That will work as long as you don't seek to use the event in it. Because it'll be like JavaScript will take more arguments that a function uses and not just ignore them. In JavaScript, you took a function and took two arguments and past it. Nine, it'll use the first two and ignore the other seven.
[00:12:44]
And so it'll work until you try to use that event and it'll be like, I don't know what you're talking about. Type script is kinda cool, it's got the same type system as OCaml. You're like, cool. Who amongst us has write OCaml in our free time. One of the nice things is instead of Java, if you've ever seen that enterprise FizzBuzz meme.
[00:13:02]
Where they have to make Abstract Factory abstract class for everything like TypeScript. As long as it roughly matches what you're looking for, TypeScript is totally okay. That's kind of endless what we think about what JavaScript too, if you're saying. This thing should have a first name and a last name, and that's the type full name.
[00:13:22]
If you pass another just regular old JavaScript object that has a first name and a last name property. TypeScript, like thumbs up, even though you didn't explicitly say it was that type. And so like, you can get away with stuff until you do something that's actually going to.
[00:13:35]
Like it's about as forceful as it needs to be and no more than that. Until you try to use it, and we'll actually see that in another example I believe, later on too. But yeah, you could have done event is even like HTMLElement, and actually should be void.
[00:13:56]
And you can try to write your own, but generally speaking, it's super nice especially if you're gonna pass it through. Just to be like, hey, I'm expecting this function that matches what I'm going to pass it to is better than trying to write your own types. That mostly match up, because eventually, this will lead to sadness.
[00:14:13]
Eventually, you'll be like slightly off in one use case. And then you have to stop what you're doing and pay down your debt.
>> This assignment stuff.
>> Yeah.
>> One other thing, do you do it in the interface slash type above, just in case you want to add more props than name on change?
[00:14:30]
>> Yeah.
>> Later on?
>> Yeah. You can see that if I was in lining it in here.
>> Yeah.
>> And have I taken this to its natural conclusion before breaking it out, of course I have. But you can see that trying to both have the properties in here and then also to find the types.
[00:14:45]
>> It gets, yeah.
>> It gets ridiculous, and then if I ever do need to export that out somewhere, guess why I end up with?
>> Yeah.
>> So for me normally my workflow is every part of me wants to do it in line. And most parts of me know that I will regret it.
[00:15:02]
And then so, if it's early in the day, my willpower and I can resist the marshmallow on the table. I will break it out into a type later in the day, things get a little bit fast and loose. And then I make poor choices and inline it, but then I always eventually have to pull it out on a long enough timeline.
[00:15:19]
If it's just one argument, you don't want to do all that extra work. Yeah, sure put it in there. But generally speaking, I will try to break it out into a type I really wanna change this back to a type. I also wanna change this back to [LAUGH] I wanna change all of the things I was just talking and typing at the same time.
[00:15:46]
The nice part is I can also just grab it from here. If I hit tab, I can auto import it. From react
>> But it's a generic righ,so I think we.
>> Yeah, I was hoping the autocomplete was gonna pull it in I got distracted for a minute.
[00:16:11]
Didn't auto import, so I was just gonna say react. Cool, all right, so that's back where I wanna to be. Pull this out too. Let's go ahead and immediately regret previous mistakes here. Type NameBadgeProps pass in that name. And if I want to say something that's optional, I can just say like greeting?
[00:16:48]
And if it exists it should be a string. Now if I look over at this I'll see that it can be a string or undefined. And what's really cool about this is, if I ever try to use greeting like it exists, TypeScript will yell at me. Hey, that could be undefined, right, and so if it's something that that matters like strings.
[00:17:10]
It'll just coerce into an empty string a lot of times, no big deal. But if I'm trying to actually use that value in some of this, definitely having a string or something along those lines it will force me to confirm that it exists first. And we'll actually see that again in a little bit of a later example two where we'll see that like I can't use things unless I confirm that they exist.
[00:17:31]
And some other like features along those lines and then after I confirm exists then I'm free to do whatever I want so on and so forth, yeah.
>> I always had that confusion about, since we're using the question mark optional TypeScript, right? Technically the need for null for now goes away completely.
[00:17:48]
We use undefined as the absence of value, right?
>> Yeah, I will sometimes use null is like explicit. Yeah, like I use no in TypeScript the way I'm supposed to use now that I haven't always used before, which is like explicitly nothing.
>> Because sometimes I've seen people make mistakes when, let's say, you mark it optional or something from libraries marked optional.
[00:18:08]
And then instead of just using I guess a truth value if that thing somebody explicitly does equals null that's
>> Yeah.
>> That it's gonna fail but, but just because it's a silly mistake,
>> Yeah.
>> But okay, so thank you.
>> Yeah, and we'll know that you can't pass it null like if I tried to pass a null in here, I get yelled at, right.
[00:18:31]
It's like string or undefined. No zeros. No falses. Right, like string or undefined. Undefined can be falsely and that can be a check, but it will know that case like I will limit it down. We'll see a few other examples where it's like things I normally would have done a whole bunch of type guards for like in regular JavaScript.
[00:18:49]
If this type of this, if it's that, if it's the other thing, right? I don't wanna talk about how many times I've gotten bitten by the fact that zero is false. I'm not interested in talking about that. It will save me for that. So we'll actually see this kind of like, I wanted to point out now so that when we see it, we're already mentally aware of it.
[00:19:12]
And yeah, now I can pass this in I can say like and we got to pass them to the props too. Look at autocomplete. Yes, right in this case like I don't get yelled at because like passing an empty string into an HTM element is fine, right? Or undefined coerces into an empty string in this case.
[00:19:31]
So that's totally okay. But if I tried to use it for some other value, we will get yelled at. But you'll see that as I was starting to use this component, especially if you're making like this is all in the file. If I was then using this component somewhere else, I implicitly have documentation on this component, right?
[00:19:48]
I can't really use it wrong, try me, it is harder to use it wrong. How about that? And so like implicitly you get documentation, implicitly you get safety checks as I use this component other places.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops