Skip to content

noVueUndeclaredEmits (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noVueUndeclaredEmits": "error"
}
}
}
}

Require Vue components to declare the events they emit.

A component lists the events it can emit with the emits option or with defineEmits(). This list tells other developers which events they can listen for. It also tells Vue which listeners belong to the component: a listener for an event that is not in the list, such as @close, is also added to the root element of the component. If that element sends a native event with the same name, the listener runs a second time.

This rule reports each event that is emitted with a name the component does not declare. Events are emitted with this.$emit('name'), with the emit function of the setup() context, with the function that defineEmits() returns, and with $emit('name') in the template.

An event named update:name counts as declared when the component declares a model called name with defineModel(), because Vue declares that event for the model.

The rule doesn’t report an event when it can’t know every event the component declares. That is the case when:

  • the list of events is not written directly in the component, as in emits: eventNames or emits: [...baseEvents];
  • defineEmits() uses a TypeScript type that is imported or can’t be read;
  • code written elsewhere adds to the component: mixins, extends, an object copied into the options with ..., or a <script src> block.

The rule also ignores events whose name is not written as a string, as in emit(eventName).

import { defineComponent } from "vue";
export default defineComponent({
emits: ["change"],
methods: {
close() {
this.$emit("close");
},
},
});
code-block.js:7:18 lint/nursery/noVueUndeclaredEmits ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The event close is emitted, but the component doesn't declare it.

5 │ methods: {
6 │ close() {
> 7 │ this.$emit("close");
│ ^^^^^^^
8 │ },
9 │ },

ℹ Vue also adds a listener for an undeclared event to the root element of the component. If that element sends a native event with the same name, such as click, the listener runs twice.

ℹ Add close to the emits option or to the defineEmits() call of the component.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<script setup>
const emit = defineEmits(["change"]);
function close() {
emit("close");
}
</script>
code-block.vue:5:8 lint/nursery/noVueUndeclaredEmits ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The event close is emitted, but the component doesn't declare it.

4 │ function close() {
> 5 │ emit("close");
│ ^^^^^^^
6 │ }
7 │ </script>

ℹ Vue also adds a listener for an undeclared event to the root element of the component. If that element sends a native event with the same name, such as click, the listener runs twice.

ℹ Add close to the emits option or to the defineEmits() call of the component.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<template>
<button @click="$emit('close')">Close</button>
</template>
<script setup>
defineEmits(["change"]);
</script>
<template>
<button @click="$emit('close')">Close</button>
</template>
<script setup>
const emit = defineEmits(["change", "close"]);
function onInput(value) {
emit("change", value);
}
</script>