Declaring and Typing Component Props — Transcript

Transcript of the free Vue.js lesson Declaring and Typing Component Propswatch the video lesson.

With all of our created entries now stored in the entries variable, we need a way to pass those entries into the entry card component. That way we can display the proper information in the card. The solution? Well, props of course.

But how do we work with view component props in TypeScript? That's the question. Well, I'll open up the entry card and then within script setup, we can define props with the define props macro. Our first option here would be to use what's known as the runtime declaration by passing an object to define props.

Then we can define any prop we'd like with the syntax you're probably used to using with plain old JavaScript. However, we're wanting to accept a prop that matches that TypeScript interface that we created earlier for the entry. So let's try to do that with the runtime declaration. First, I'll import the entry type.

Then I'll define the entry prop and assign it the type of entry. When I hover over entry, it says entry only refers to a type, but is being used as a value here. Remember, we're using a runtime declaration right now, and the TypeScript interface entry is not a runtime language construct. So...

Using a TypeScript interface with a runtime declaration just isn't going to work for you. So what's the alternative? Well, instead we can use what's called the type-based declaration for our props. And that looks something like this.

We'll remove the object that we're passing to define props. Then I'll add some angle brackets for a generic type argument. And pass it an object literal containing the props we'd like to support. In our case, that's just the entry.

Cool. Now the error has disappeared and we can use our entry interface. But we can still use simple built-in types as well. As you might expect then, using the type-based declaration is typically preferred over using the runtime declaration when you're using TypeScript.

Also note though that you can't use both styles within the same component. You've got to use one or the other, that is the type-based or the runtime base. Alright, now we could define the props as a separate interface altogether, just above defined props here, and then pass that interface to the generic type instead. Just be aware that if you do choose to go this route, that you must declare that props interface within the same file.

It cannot be imported from a different file due to the way the template compiler works. I don't see any real benefit to this though, so I'll just move it back in line. Alright, now there is one primary downside to type-based declarations, and that is you lose the ability to declare default values for the props. This can be resolved though by the currently experimental reactivity transform feature, and that looks something like this.

Don't let the red squiggly line here fool you. It's just not up to date with this experimental feature. There's one more thing we're still going to have to do since this is experimental. That is, we have to opt into the syntax by setting the reactivity transform option in the Vue Vite plugin to true.

To test out the default values now, I'll just give the Vite dev server a quick restart since we have modified its config. And you can even see the message in the console warning us that reactivity transform is an experimental feature. All right, now over in the browser, if I add in a new entry and then check things out in the view dev tools, we should see the default value for the random prop. And sure enough, that's exactly what it is.

Nice. All right, let's just remove the random prop now since it's not needed for our project. And then we'll take this back to just a plain old type-based declaration without the default values. Now, within the template area of our component, we can render our entry information in all the proper places.

First, we can provide the entry body and the entry at created date. We'll just leave the hard-coded username for now. And for the emoji, we can provide that as well. Okay, we've got a red squiggly line.

So it looks like I accidentally typed the argument to this findEmoji function incorrectly in the boilerplate code. ts under source slash composables, and then double click on the definition. That takes me over to the spot in the proper file where I can just change out the type to emoji or null. Note that emoji was auto-imported for me.

view Notice that without the entry prop provided we do have a red squiggly line telling us that there's an error That's because entry is required If we wanted to make it optional, we could use the question mark in the type declaration. And cool, that makes the red squiggly line go away. But we do want it to be required, so I'll just remove that question mark. view, let's provide the prompt.

And notice that as we type, in our autocomplete list, we have the proper suggestion. Awesome. Now we can pass the current entry in the loop. This results in no errors.

since the entry that we provide to the entry prompt conforms to the entry interface. However, if we were to provide a value that didn't conform to the type of the prompt, then we would get an error. Nice. All right, let's just change it back.

Over in the browser, things should be working pretty great now. Let's create one entry to see what it looks like. And no dice. Let's check the console and see if we've got any errors.

There's actually plenty of them to choose from. view. Yeah, when we use the defineProps macro, we don't need to set the result to a props variable. That way we can have entry directly available in the template.

Now let's give it one more shot. I'll start by refreshing our page just so that we can clear out our console and check it for errors in a moment. Then I'll create a new entry. Cool.

The card is added below the form and it has the proper values displayed. Let's try one more. Works like a charm. Lastly, let's just check the console one last time to make sure we've eliminated all the issues.

Perfect.