Check out a free preview of the full React and TypeScript course:
The "Reusable Props Interface" Lesson is part of the full, React and TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Steve live codes refactoring the color inputs to appease TypeScript. The hard coded input will be swapped out for what the user passes in and avoid errors with TypeScript because the input will conform to the type required.

Get Unlimited Access Now

Transcript from the "Reusable Props Interface" Lesson

[00:00:00]
>> We still have to, TypeScript's gonna be angry with us. And what we're gonna need to do for the next little bit is to make TypeScript less mad at us. So, first thing that it is mad at us about is, well color swatch doesn't need anything anymore. Color sliders also doesn't need anything any more, either I'll comment out the inputs for now, we'll get to those in a second.

[00:00:25] But we still have this problem that I just kinda hand waved to and ignored there for a second there, which is, okay. Yeah, no, I'm not okay with this. Because we don't know what it's gonna be. So we could say that listen, we can do it, we didn't sell this the same way we solved with some of that state, you state stuff before.

[00:00:42] We can say listen, yeah, it can either be the RGBContextType or it can be null. Look, everything's mostly okay, here, right now. But not everywhere, because now it doesn't know if these properties exist on this object, right? Because if you're trying to pull red, green and blue off of null, you're gonna crash, and TypeScript doesn't know how to save you from yourself in this case, right?

[00:01:18] And so you could do something where we comment, let's copy this, and we'll comment it out for a second and we'll just say, Just name it something, right? It's, this can be value, or it can be null. Test group has, i believe this is in JavaScript now, too, where you could say something like, console.log, value.

[00:01:49] ?.blue, which is basically, if value exists, then pull the blue property off of it, right? And if you swapped out everything in your code base to use value, ?.blue, you would appease TypeScript, because all TypeScript is trying to say is, I cannot promise you that it's not null.

[00:02:10] And I can't let you just call this property because just because JavaScript lets you doesn't mean I can't, in good conscience, let you call this. And so it's saying, please just make sure it's there before you use it. So it doesn't work, and you could do this all throughout your code base forever.

[00:02:32] My argument to you is just going to be don't, right? And so that's where we have some other options here, to have TypeScript be less angry. Because to be clear, TypeScript's not wrong. Many of us have been caught by bugs just as insidious where it's, such and such is not a property on undefined, right?

[00:02:57] It's happened in a JavaScript code base before that you have thought something was an object when it's not. So as much as it seems kind of annoying, it's not too bad, it's a good idea. So one of things that we can do is TypeScript has this keyword called as, and as allows you, To, say listen.

[00:03:21] I understand what you think is a type system, but this is a situation where I know better, and just trust me. So we could say here's an empty object. And we're gonna say but just pretend that it's an RGB context type, right? And because the default value is now an empty object, calling those properties is not problematic.

[00:03:44] It's not gonna blow up, they'll just be undefined, which could be problematic in your code base. But really, we know that this is effectively set on the next line, right? We are confident, we, in this case, find it within our power to override type scripts like built-in mechanisms, cuz we know what we're doing.

[00:04:07] Another place where you might find yourself using this is in that character cards that we had earlier. The alignment when only ever good or bad, but TypeScript is assumed that it was a string. And so if you pulled it from an API, TypeScript might not be able to know that.

[00:04:22] But you could be, listen, this JavaScript object, I know that it's going to be this type, that it's only good or bad. Trust me, even though you just got this JSON response back from the server. So it's times where you have enough confidence. You feel that you're able to take a little bit of the risk here to know that maybe the property read is not on here just yet, but we know this isn't even a asynchronous event.

[00:04:46] So we know in case it's happening. There is a third way to do this. I'll kinda just tell you what it is now, but we need to know a few more things before we can implement it without you just staring at me, yeah, great, he's writing complete gibberish.

[00:05:03] But the other way is to kind of create an abstraction that will, in the same way we had to check to see if value was null or not. We could create our own useContext that checks to see if it's defined before it lets us use anything, and just take all those checks and put it in one place.

[00:05:16] That is arguably the correct answer. To be clear, this is what we do, we know in this case. If you didn't need dispatch, you could say you can even define a green, red, green and blue value here, and only put in dispatch lane. There's lots of ways to handle this.

[00:05:38] Generally speaking, I think that this will do the trick most of the time but understand you're taking on a certain amount of risk. So yeah, that is some of the problems that come with the fact that a lot of the safety and benefits here are really good. But we are ultimately building on top of a language and platform that wasn't always immediately there for this.

[00:06:01] So one of the things the problem we have to solve for, and again the very beginning of this course, right? Yeah, just say that your strings are gonna be strings, everything's great. Where are the pain points with React and TypeScript start to come along is when you start to do some of the more advanced React patterns.

[00:06:20] Cuz like most things, the easy things are easy, and the weird cases are when you try to do some things that are a little bit trickier, all right? So if we look, our color sliders and our color inputs are roughly the same. We're just basically using, we're defaulting to the built-in HTML elements.

[00:06:44] So this is an input with the type range this one, the color slider, this is one, yeah, type range. And then the color input is just a regular type number, right? But other than that they're mostly the same other, than some formatting and stuff that. It'd be great and then the sliders floor I'll just create the red, green and blue for each.

[00:07:07] I'll show them to you real quick. So color sliders, yeah, it's just three of them, color inputs is roughly the same thing. Would it be nice if I could just use them kind of interchangeably? And one of the things that we can notice is that previously, the sliders we took over the individual side was actually still to this moment.

[00:07:30] Take ID label and value, we're gonna need an on change in there as well, the inputs right now don't do anything. And the slider, it is id label value and then the on change that we're gonna put in both places. It'd be great if I could create an abstraction here, right?

[00:07:50] I would love to just be able to say hey, they take roughly the same props, or in a few minutes exactly the same props. Wouldn't it be nice to simply define, okay, here's the props that I'm expecting that are kind of similar to both of them. And just say like, all right, for you, I wanna say here's the color input component, make me the three of them wire them up.

[00:08:15] For you, color sliders, do the same. So one might think, no, I had to specifically type everything, there's no way that I can be dynamic with what component I pass in and have it conditionally rendered, right? All right, so let's, let's take a look at the next one that I wanted to show you which is that's the wrong one.

[00:08:28] Not right? So let's make a new one called color adjustment. And so okay, we're gonna have an interface here. It could be a type, and this is gonna be our AdjustmentinputProps. And what [INAUDIBLE] id is gonna be a string. A label is going to be a string, Value will be a number, and then on change.

[00:09:02] Is going to be an event, and we know that it's gonna be a change event from HTML input elements. Luckily, they're both HTML input elements. And that's going to return void, so we have this common type now. And what we're gonna say is listen, you can pass me in any component that you want as long as it adheres to this interface.

[00:09:29] You wanna use this color input, fine. You wanna use a color slider? As long as you pass in a component to this corner we're building right now that adheres to this interface, we'll be able to work with it dynamically. So then, the props for rendering, the three will be an interface, color adjustment props, just like we've seen before.

[00:09:52] And again, this is really gonna take one thing which is, what component that I want to render. And I'm using capital A cuz I'm gonna talk about a React component. And so, this is one that we'll use, called React. We're gonna talk about these in a second a little bit more.

[00:10:08] I'm just kinda introducing the topic now of what we call utility types. So React.ComponentType is, Saying, okay, I got pull in react, hold on. Input. From react and then adjust it, let's go with adjustment. I like that one, better, what we're gonna say is the type of the prop that we're expecting.

[00:10:44] Previously, we've seen string, number, boolean. Some objects, we're gonna say is, the adjustment prop on this component can be any component that adheres to these properties up here. All right, so as long as we pass in something, a component that has the same interface, we can pass it in dynamically.

[00:11:06] So let's actually just grab, I'm gonna grab the color sliders. Real quick, and I'm gonna reuse most of this code. So we'll just grab that and paste it in. And at this point, we do need to pull in react.use.context. And we'll import RGB context as well. Context, sweet, the only thing that's blowing up right now is I haven't pulled in the color component cuz we don't actually wanna use the color slider yet.

[00:11:53] What we want to do is whatever adjustment has been passed in. So we know that the only prop that this takes is adjustment. And here we'll say, Yeah, that's just our color adjustment props. And then we can swap it out saying whatever component is passed in, instead of rendering three color sliders, do whatever component was passed in.

[00:12:25] Right, so this works, we just need to use it, so we can kind of swap it out. So go into application and we're gonna say is instead of color sliders we're gonna say color. Yep, wait for it, Import color adjustment, Color adjustment, the values are in red, that's fine.

[00:12:59] But yeah, my suspicion when autocomplete didn't work is that I didn't export it. Or I called it, All right, that should work now. So we've got color adjustment, and now we can basically say all right, instead of saying color sliders plural, what I want you to be is a color slider.

[00:13:25] I'm sorry, ColorAdjustment. And the adjustment component is gonna be a singular color slider. All right, and then we can go ahead, we put more of those in there. I can also change this to a color, Input, and it will render both of them. So now, I can just make changes to this one kinda higher order-ish component, and, it's not hard coded as you can only have stuff to put in anything that confirms.

[00:14:04] To this adjustment input props will work and we can start dynamically passing in react components. Well, as we just need to figure out what React gives us in this case as well. And so that came from the utility type of React.component type.