Check out a free preview of the full React and TypeScript, v2 course

The "Auto Complete" 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:

Steve adds auto-complete for props being used on HTML input elements. The type definition for the props uses the ComponentPropsWIthoutRef to union an HTML input's properties with any additional custom props.


Transcript from the "Auto Complete" Lesson

>> Let's talk about one more small thing that makes me happy. Pop quiz for 75 points. They're points in super Mario, they don't really do anything. What is the one thing that makes me happier than anything else?
>> No anys.
>> What's that?
>> No anys.
>> No anys, because what?

What do anys mess up?
>> Everything.
>> Everything.
>> But in particular autocomplete. [LAUGH] In particular, autocomplete, right? I tell everyone else in my team we're using TypeScript for reliability and type safety. It's totally why we use it. Also, I like autocomplete. It's amazing to me every time that it works, right?

You probably noticed that as I was talking. So I kinda typed an empty string I saw those action names, it's the first time that I ever saw it in my life, right? Every time it makes me that happy. So can I talk about what doesn't make me happy, which is the opposite of what makes me happy, right?

So let's take a look. I have these, if you've never done this you are my hero, and I appreciate you. Which is every app, I'm like this time I'm not gonna do this. And I'll have a button cuz maybe I wanna have a primary button and a destructive button and a secondary button, right?

Or the one that I always end up with. Maybe I just wanna have a form input that is a label wired up for the right ID, right? And I don't have to put them both together and then realize that they're both inline blocks and then change the styling on the two of them, how they play together.

Or a buttoning component, a submittable input feel. When I worked at Twilio there was another team that worked on the design system, I'm very glad that they worked on the design system cuz I didn't want to. And yet on some small level, I end up having to build my own little mini design system all the time.

It's just little stuff like this. Like a button that I can use that has the right styles and all the things that I want, right? Passed in. But here's the thing, I'll do one you can do the other. I think this is the one that annoys me more so I'm gonna do this one.

Okay. What do you notice about these prompts? How many of them are original and once you've never seen before? Technically only this one, right? That's just to put some label in here, right? The rest of these, I am just passing through. And what would happen the first time I needed to autofocus one of these, what I'd have to do?

I would have to add another prop. First time I wanna make one of these required. If you don't have to do, add another prop. Yeah, I can keep going with this example I think we get the point. In regular JavaScript, I might choose to do something like this.

So label is special. I think that's the only one that was truly special, like Read Only. I got yelled out about uncontrolled inputs for the like, it's very rare that you show people app, where none of the state management is hooked up, right? Unless you're teaching. So I was like, call it a Read Only if there's no way to update the value.

How about that? So that's bespoke cuz I was staging and I was trying to be as like yelling at me. But generally speaking, I really just wanna wire up HTML for it to the same ID as the input ID. And I would like to pass on a custom label and I would like to wrap it in a DIV to treat it as one package, right?

I don't wanna do this all the time. So what I would end up doing JavaScript is you just do label, take the rest of the props, And go in here, we'll keep my custom ID. I guess I'm gonna use the ID for a second cuz I'm just in case it's not a unique one I take this hook.

It's mostly for service ID rendering it gives you unique identifier so I know that all my inputs have unique IDs. So keep that. We'll keep the read only in there other than these two things. Anything else that comes in, Spread it out. I guess I need on change in this case too.

Cool, cool, but you'll notice is angry with me, right? One, cuz I didn't put a comma. And now it's angry. It should be somewhere else in a second. Well, I don't get any auto complete. If I get rid of these now, ready? At least these. I can't use them so I get rid of them here or the label I needed.

But you can see the red popping up. It's like hey, these don't work and stuff like that. It's shows up on label but it's actually saying, you gave it an on change. I don't know anything about non change. Now if this code were to compile, if I change the file extension, it works.

But other fun stuff. No autofocus. No nothing, right? So not only do they not compile, this problem number one. Problem number two, I got no autocomplete, right? And button is the same way. I'll let you play around with button in a second. Like I want. If wrapping a button, especially like a button.

I'm literally just returning a button. Pretend special button where I'm just playing around with the classes a little bit. Pretend you're a button, button, who is a button that I've wrapped. So what I really wanna do is I want to create a type where my custom stuff, label.

And then all the things that are part of a regular, whatever the input field is. And I think that was a yesterday question before we saw it with component props, without ref and component with ref and stuff like that. Which is there is a way to access all of the props, right?

And so, what I can do is I can basically say hello, I would like to create a type that is my special stuff, plus all the types from another component. And we can do that super easily. And let's try it out with that labeled input, where I started it.

Which is okay, actually even these two. It was just label that I wanted. I wanted label to be string. And I'll change ,can be the normal one. And so I'm getting yelled at all over the place, everyone's angry with me. And what I can do is I can basically say, If I don't think I'm gonna use a ref, I'll start with this one and wait.

Which is to say, take everything from an input. And now if I look at this, it's grabbing it from the actual types. It is literally everything from the built in, which is an abstraction. It's a set of abstractions. TypeScript has a lib dot DOM dot data, Ts. Then there's JSX and Trinsic elements, which are like kinda JSX wrappers on top of that.

Then there's all the React extra stuff, like the React handlers, so on and so forth. And so you can see I'm getting some of that in place here. And you can also see nothing is angry with me anymore, right? Now because I'm spreading these all on the right place, and theoretically you could override read only cuz actually yeah, the prompts coming in afterwards.

So you could actually even override this one too cuz it's like order of operations. Cool set this one, set this one and then this question on the order of operations on that but it's not important right now. Cool, so now if I go back to a place where I was blowing up before.

I get everything that an input field can do. And none of the stuff that I can't do, right? And all of that is kinda built in with the article. But as far as TypeScript is concerned, my special labeled input, is in fact has all the properties of an input field cuz I was explicit about which ones were passing through, right?

And you could see how you can take this technique. You could like, okay, and a label, but I wanna take some of these. There's danger with some of that. With all programming the fancier you get, you start walking on the razor's edge a little bit and just to be aware of that.

But generally speaking, for some of these very simple mini design system components that I end up creating, I can definitely do that, right? And it's a super powerful trick to do, right?
>> Yeah, wouldn't this also require you to pass, let's say there is a required property and something marking the input as the props of some element when this also force you to pass those required properties in when you wouldn't otherwise.

>> I mean, if I'm wrapping I think where they would be required, they're gonna be required one way or the other, right? To answer your question, if for some reason I needed to get super nuanced, right? And so let's hypothetically answer the question. Let's say that for some reason, the regular DOM components don't have any really required properties, right?

Cuz turns out the DOM Pre days TypeScript. So it's fast and loose. You've never seen the HTML page crash. Think that's a true statement? JavaScript and crash HTML, the browser will do everything to make it work. But let's imagine we desperately wanted to create one of these without autofocus, right?

At which point we pull out one of those utility types we saw before. When we say omit, And you have to do this a lot of times with more complicated components. And then here we might say that, I don't know, right? [COUGH] And you could do something along these lines, right?

Where you say, cool let's take a button that's got everything but this and then I have thoughts on what this one should be, right? I'm yelled at because I said it was required this time, right? I didn't put a question mark. So now I can create one where I'm forcing which to force autofocus on all of them was a weird choice on my behalf.

The easier with HTML it's easier to answer the opposite of your question. You're like, what if some require wanna make it optional, right? In the case of HTML elements where everything's optional, it's easy to make something required. But by saying everything but this, but then I have strong feelings about this, actually we can make it required.

And if I omitted it completely, we have now removed the ability to have autofocus whatsoever, right? So you can compose and put together recipes of these types in a super powerful way.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now