TypeScript and Vue 3

Compiler Macros: defineEmits

Ben Hong

Ben Hong

TypeScript and Vue 3

Check out a free preview of the full TypeScript and Vue 3 course

The "Compiler Macros: defineEmits" Lesson is part of the full, TypeScript and Vue 3 course featured in this preview video. Here's what you'd learn in this lesson:

Ben discusses defining and emitting events using the defineEmits macro. The defineProps and defineEmits compiler macros are only usable inside <script setup>. They do not need to be imported and are compiled away when <script setup> is processed.


Transcript from the "Compiler Macros: defineEmits" Lesson

>> So now that we have this, we have this other thing called emits. And so to kind of basically provide a quick overview for those who might not have used it in View 3. If you remember inside of your code, whenever you wanted to emit an event within Vue, you would actually use dollar sign emit.

So let's say this click handler right here, you say emit and then some sort of event. So this would be test-event. And so where am I? I'm on the restaurant card. So, if we go over to our app, and go to our restaurant, yep, we'll see here, wait, something, okay, we're good.

So if we go inside of the Vue dev tools, and let me pull this up a little bit. Wait, restaurant card, yes, okay, yah, yah, I'm in the right place. And then let's go to the timeline. You'll see that when I click Delete, it's actually showing me here that, [SOUND] here it is, here's the custom event, here we go.

It's fired off this event called test-event. And so this is actually, for those who haven't used it before, this follows basically basic JavaScript conventions, right? Because you have an event that's triggered somewhere, it bubbles up and then you wanna do something with it. So that's how currently we're working with our cards right now, is that it's emitting an event, like delete restaurant, for example, and then the parent who has the data will then go ahead and perform the necessary tasks to do that.

So, the thing is, especially in Vue 2, this was actually all that you basically did. And what happened was, components got a little bit complex because you had this emitting events here and there. It was kind of hard to track. And so in Vue 3, we introduced an option similar to props where you can define the kinds of events that the component is emitting.

And so typically, what we saw before is that it's just defined as an array with the list of the names of the events. But with the compiler macro and TypeScript, I do think it gets a lot cleaner. So we have here is we can say, defineEmits, and then inside of defineEmits, it can take an array, just like this.

Or rather than having just an array like this, I'm gonna comment this out so that we have this for comparison. We're actually gonna give our events a type, and this is actually super helpful particularly with events. Because what we end up getting is the ability to say, okay, so we have an event that comes in, and we can say it's just a generic event.

But you could also be specific. You could be like, this is a keyboard event, and that keyboard event, we'll do more of event handlers later, but this is pretty nice. So for now we know that this event is gonna be called delete-restaurant, just to double check, yep. So you have your e here, you pass in the name of the event that's gonna happen, and then after that, you're gonna pass in whatever payload that it's expecting.

And then whether or not it's supposed to return anything, and it typically not, so it's void. So in that particular case, we have e here. We know that it's gonna have a payload and the payload is going to be, [SOUND] it should be restaurant. So we'll type that just like this.

Okay, there we go. So what's nice about this now is that when we wanna actually use this, right, cuz before all you could do is define the name of it. So now when we call the emits, something pretty cool happens. When we emit the thing, if I hit Command+Space and hit Up, you'll actually notice that it actually lists the event names that we've defined in the auto complete.

So even though it's a string and not a constant, it actually knows that, hey, I actually should look for this string. So not only can I do that, then I can even say, okay, well, if I did 123, for example, it'll say hey, by the way, this particular event is looking for a restaurant.

And this is pretty big because as we know, events can be really clunky to manage in JavaScript, especially cuz there's different types and we expect it to do different things at different times. So being able to type your events and be very specific about what kind of thing we're expecting, that's huge.

So now all we gotta do then is basically we want the props.restaurant, and that's it. And so with all that autocomplete, you get that because you're typing your events, which, again, is something in my opinion you want to be doing. Because when you don't do something like this, emits get really, really tricky to track and much less trying to figure out what they do.

And it almost seems like every time you have to debug an event that's being emitted, you have to start over from figuring out the stack trace of why it's a certain way. Whereas here we're being so explicit that a delete-restaurant event will take a payload that is of type restaurant, that's it.

And I think that does wonders for us when it comes to actually scaling our code. So, now that we've come to the end of that, does anyone have any questions about what we just covered, yes?
>> Why don't we have to import define emits and define props?
>> That is a great question.

So one of the things that, I feel like the Java community kinda goes back and forth a little bit on this with, is that, they try to strip away any global imports that you might need just to, I guess, make it one less thing that you have to import.

And because Vue knows for a fact that you're in script setup, these are the kind of the compiler macros that I was talking about, where there are optimizations done in advance. However, there really is nothing stopping you from saying defineProps, defineEmits, because I can totally see the value in being explicit, and it's not gonna yell at you.

But on the other hand, if you're one of those people that wants to shift away as much as humanly possible, that is there for you. But I will go and leave this here for record keeping sake, and then actually I'll just fuse these together. There we go.

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