TypeScript: From First Steps to Professional

HTML Form Types

Anjana Vakil
Software Engineer & Educator
TypeScript: From First Steps to Professional

Lesson Description

The "HTML Form Types" Lesson is part of the full, TypeScript: From First Steps to Professional course featured in this preview video. Here's what you'd learn in this lesson:

Anjana continues fixing errors in forms.ts by adding types to resolve implicit any issues. She highlights the importance of understanding HTML and DOM interactions and demonstrates how to specify types for both functions and variables.

Preview
Close

Transcript from the "HTML Form Types" Lesson

[00:00:00]
>> Anjana Vakil: Uh, let us continue getting rid of these errors And meanwhile, we can keep an eye on our tests here and we've at least got some passing, so that feels nice But let's continue looking at these problem files and see if we can do something about it Taking a look at our Forms.ts file Well, we've got our good old friend, implicit any error, so we need to add some types

[00:00:33]
Now, in order to figure out what kind of type this function is expecting or should be expecting, we're going to need to think a little bit about what's going on here and has something to do with Forms and data that are coming back from them and buttons and inputs and all of this stuff So what does that sound like if I'm talking about buttons and inputs and whatnot

[00:01:05]
It sounds like I'm not talking about Node things that happen on the backend, but rather we're dealing with HTML The DOM here This is something where we're going to be having things like in this event And this really, really sophisticated web framework where we are rendering strings that represent HTML elements, we have this form element for each event which, let's see if our site is still up, OK

[00:01:44]
Which is something you might have when you were poking around You might have clicked on some of these buttons and seen that there is a little tiny mini form where you can say, I want to go, and you put in your name and you put in your email And again, this is super simplistic Not how a real web app would work, but it serves our purposes And so it's a form, it has buttons

[00:02:07]
I can inspect it in my browser if I want to And see that I have, oh goodness Yes, I have this form element here, and it's got a bunch of stuff in it, including labels for fields, for inputs and blah blah blah And then there's a little footer with the buttons and yeah, yeah, yeah So we're dealing with forms that the events module is going to be kind of rendering if we're thinking about it like as if it were, you know, doing that

[00:02:42]
It's really just outputting strings right now and we're pretending that it's like a web framework, but so what we are working with in this forms here is, if we look at where setup forms gets called, we see that we're doing a document query selector all form And this is just JavaScript, this is just interacting with the DOM And if we hover, TypeScript knows about documents and it knows about query selector all, again, because this is JavaScript stuff

[00:03:24]
And we told it in our config file if I do tsc show config again, and make it big, and we might have noticed earlier this little lib array where we're kind of giving TypeScript some information about things like the DOM And so, for example, if we were running a Node JavaScript file, we wouldn't be doing things like document query selector all because we don't have a document, we're not dealing with HTML, but here we are

[00:04:03]
And so that's actually something that Vite client type, uh sorry, the Vite React base config that we extended had all of this client-side frontend HTML web stuff in there because that's what that config base was set up to do is for frontend projects using Vite and possibly React We're not using that part, that's cool Anywho, so just another note on the fact that TypeScript knows a lot about what's going on here, and we get a clue as to what type we might want to be adding in our annotations from the return type of this function, if we hover over it

[00:04:50]
There's a lot going on here We have more parameterized angle bracket situations We've got a selector called Form, but eventually we're getting a node list of HTML form elements And that is a built-in type that TypeScript knows about, because JavaScript knows about it These are types that correspond to all of those DOM entities So, the RSVP forms that we get back is going to be, it's not an array but a node list, close enough, whatever

[00:05:33]
And the TypeScript compiler infers from how we are writing this code that since RSVP forms is going to be a list of HTML form element nodes in the DOM tree, that then if we do a for of, the individual element is going to be an HTML form element And so indeed, set up form, when we call it, is receiving an HTML form element However, when we hover over set up form, the signature does not know that

[00:06:17]
So we need to tell it that And there's one other word in here that we're not going to spend too much time talking about, but this void Is it, are we just talking about the abyss that we stare into when we work with TypeScript or web development in general Void is a special TypeScript type that represents a function that's not supposed to return anything

[00:06:42]
So for example, if I have a function that's doing something side effecty, like just logging to the console and I don't want it to return anything, I can use the void type to indicate to TypeScript, OK, there should not be a return value from this, and if there is, something weird is happening So it's kind of the function returning nothing, nothingness

[00:07:06]
So many different kinds of nothingness Did you even realize how much nothingness there is in the world Because TypeScript did OK, we're not going to worry too much about that Again, it's another, uh, more of a big void that we could easily lose ourselves down the rabbit hole of OK However, now we have a clue as to what type we need to give our function signatures

[00:07:37]
So I can start doing that with HTML and notice as I start typing, VS Code very helpfully starts suggesting every single HTML element it knows about And oh boy, there's a lot Luckily, we happen to know because we've read through and we're humans and we can understand what we're trying to do with this code that we are talking about an HTML form element

[00:08:09]
So now that I have declared that type here, the form variable now has a bunch more information where it used to just be any However, eventually, we get to this send data form, and we have a similar problem TypeScript knows the value of form is going to be of type HTML form element, but we didn't type the send data function that we declared That's not a built-in thing that TypeScript knows about

[00:08:43]
And so again, now here we've got an asynchronous void But we most importantly, don't know that send data is supposed to always take in an HTML form element until we tell TypeScript that And it even is helping me I started misspelling this I wrote a lowercase l, but it's like, no, no, you wanted this thing, didn't you And I can press tab and it corrected my misspelling

[00:09:21]
OK, just to make us feel accomplished, let's see how we're doing in our error count We're down to 3 Huzzah All right, but we still got 1 more in this file, and it's this hebaba And this is saying something confusing with a lot of different syntax and something called a symbol iterator, and what we're getting at is under the hood of how iteration works in JavaScript and this .entries method

[00:10:01]
But this is a method that exists that's kind of similar to how we call object entries on stuff, that if we look at it, we see that it is a, if we look right here in this, it's a method, form data .entries gives us something that we can iterate over with like a for loop for all of the data that's coming out of our form So like name and whatever I typed into the name input, email and whatever I typed into the email input, and so on and so forth for all the form things that we could use

[00:10:41]
And so the problem is we forgot to call this like a method And so here, it's like, uh, whatever you are giving me here, it's not something that I know how to do a for loop over, because it doesn't have an iterator and that's getting under the hood of like how iteration and for loops work in JavaScript blah blah, but suffice it to say, we meant to put a parenthesis

[00:11:07]
Which now gets rid of that squiggle and gives us another It's like whack a mole And this is the TypeScript experience in my experience personally and perhaps some of yours is that again, sometimes we'll be breaking things by fixing things and then we have to go fix other things But the idea is that if we work through this process and we stay calm, ultimately we end up with much more predictable code, much more safe code that's not going to give me form ID undefined or whatever

[00:11:44]
So that is the idea here Let's find out what its new problem is Argument of type form data entry value is not assignable to parameter of type string OK Type file is not assignable to type string Any guesses what's going on here And this is kind of like several layers But we have a form, HTML form element And TypeScript doesn't really know much more about it than that

[00:12:23]
All it knows is that it's an HTML form element, and that that form element can have an entries It's going to return an array of key value pairs for every entry in the list And the type for that has something called a form data entry value, whatever that is, which is supposed to represent all the kinds of things that a form input could be giving us

[00:12:50]
And there is a way to have like a file selector in your browser, you know, when you browse for the file you want to upload or whatever, and that's not something that's going to work if we are trying to put it into a URL search parameters, which is a string of like, you know, blah equals blah and blah equals blah, like how you see on the very long with all the marketing headers or marketing parameters and things like that

[00:13:24]
So, the problem is, what if we have a file and not a string And now, in our case, we just know that there's not going to be any file uploads in these forms because they're very simple So there's a few different ways that we could fix this, but for now, we could call it a string because we know it's expecting a string, and we know that that's usually going to work

[00:13:49]
And we're going to really hope that we don't later put ourselves in the position where we're going to get some object object strings because I actually passed in an object here But sometimes we just want to get things working and we can do things that will make it happy So now, down to one error in this file, and it is this Email input is possibly null

[00:14:25]
And this is possibly the most helpful error in this file So what we have is another query selector this time within the form element where we're looking for this input But hey, what if we accidentally generated the wrong ID and maybe it had something like RSVP email undefined or whatever, and this query selector found nothing Well, the return type of the query selector method is that it can either be an element or it can be null, which means that email input has the type element or null, which means that email input .add event listener is not safe for us to call

[00:15:19]
Any idea how we can fix our code to handle the possibility that email input could be null Plenty of ways here Put it in an if block like if email input, then totally we could do if email input and then, OK, and now If email input is never going to drop us into this block if we get null here, and so what we've done is we have narrowed down the type of email input once we are inside of this if block, TypeScript knows that the type is always going to be element, because we narrowed it down with this essentially type guard, which we talked about earlier

[00:16:15]
Excellent And there are a couple other ways you could have handled this slightly different, but like, fabulous Holy cow, do you see what I see I see green, where there used to be red And I see one where there used to be many errors Let's kill it All right Now we're getting into, oh yes, OK, we have our similar little problem there If I put a .ts TypeScript knows what we're talking about and no problem

[00:16:58]
OK, now what about this We have another possible null So we could do another if, we could do a like a question mark here, which is going to say, all right, well, if this is falsey, then don't do whatever's after the question mark We could do something else like return early, like if not theme toggle, return nothing, or something like that, or we could console error, missing toggle or what have you

[00:17:54]
And then we just have to also put, sorry Hm Oh man, OK, missing toggle And let's say return early and get out of here, so that TypeScript knows that in the case where theme toggle is null, we're doing something else In this case, we're just going to abort and log something to the console, let's say It's just another example of how we could handle this

[00:18:20]
And once again, TypeScript now knows that by the time we reach line 32, theme toggle has a narrower type that's not going to be null So this is another example of us taking a wider type, that union HTML element or null and narrowing it down, and TypeScript can understand what an if block is and how code is executed in JavaScript, and it knows that by the time we get there it's only going to be an HTML element

[00:18:55]
And again, there's lots of different ways we could have handled this, just showing a couple of examples Oh my gosh Let's see if We got nothing We ran tsc and we got nothing, and that's the best thing tsc could ever give us Amazing.

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