While we were busy working on validation, we lost the type support for the real time errors variable ref along the way. If we clear everything here and use the dot notation, we're not going to get any help from TypeScript or the IDE. We're completely blind. We don't know what's inside this variable ref.
If you hover over it, you see that it's a ref with a type of any, and actually it makes a lot of sense according to our implementation. If we go back to the use form errors composable, we will see that the real time errors variable ref is initialized as an empty ref, which by default gives it the any type. And the first thing that might come to your mind is to define a new type here or an interface like this and set the properties here like so and give it a name, maybe login form validation or something. and then just use this type to pass it to the ref like so.
But is that really a good solution? Like think about it. If you're using it with the register form next, not the login form, you're going to create another type for this exact same properties that you already defined in the, let's see, form, auth form types, right? We created this file to have the types for the authentication forms.
So you would have to create another interface with the types of this and that added on each other and the values are arrays. It's not really productive, you know? So in the world of JavaScript, if you want to change the values of the properties inside an object, you would loop over the object and then pick every key and then get the value of that key and then set the new value. And that's exactly what we are going to do, but with TypeScript.
In TypeScript, we use maps. And here is how to use them. I'll define a new type here called formErrors. And that will be an object.
And the properties and the values of that object is going to be dynamic. Here is how. I'll type this array like syntax and then I'll define a variable called property. Like so.
Then we are going to use this property variable to loop over or to map over the keys of the login form, for example. And how to get a key of a type? We use the key of keyword and then we define the type. So login form.
And now in every iteration, I have the key of whatever the type that I passed in there. In our case, it's the login form. And to define the type for that key on every iteration, we just add a colon and then we define the type after that. So if I add a Boolean now, if I hover over the form errors, I'm going to see that it's an exact copy of properties that's inside that login form right here.
Um, an email and a password right there. but instead of the values being strings, it's changed to booleans. And I actually can get the exact same value as well. Remember, this is a variable, it's holding the key.
So I can say login form, and then use that property, which is the key of that object. Then if I hover over the form errors, it got back the strings. In our case, we don't want a string, we want an array of strings. And that's exactly what we get over here, an array of strings for the form errors.
Now, if I use this over here, problem solved. We successfully cloned the login form, mapped over its keys, changed the values to arrays of strings. I'll save, go back to the login page, and let's try that again. I'll use that dot notation, and now I get help from my IDE.
I know what properties I'm expecting. But there is one problem, though. I'm explicitly setting it to the login form. What if I want this to be dynamic?
What if I want to pass an argument to the form errors with the type I wanted to map over and assign the values arrays of strings to? Easy. We can use generics and set another variable here called t, or type. Then replace this login form with type, the type that this type will receive.
And now I can't call the form errors type without passing an argument to it. And it's expecting a type that it can map over. So I can pass that login form. And if I'm using another thing that might be a potential value, then I can use it right here, register form, for example, and just import that.
But for now, we're just using the login form. I'll save, hover over form errors. It is now completely dynamic. It doesn't know what it's mapping over unless you provide it with an argument and it will use the type argument that you will pass to map over the type and then assign for each key the array of strings type.
To validate this again, login page and let's try the dot notation one last time and you still have all the options inside this form. Awesome. And it's worth noting that people tend to just shorten those variables a little bit. So instead of type, they use T and instead of property, sometimes they use K, stands for key.
So yeah, here is how you might see it in the wild. And here is how you map over a type and use generics.