Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to define emits in Vue 3 with defineEmits

defineEmits is the <script setup> macro for declaring custom events that a component can emit, replacing the emits option and giving you type-safe emit functions with IDE autocompletion. As the creator of CoreUI with Vue development experience since 2014, I use defineEmits in every component that communicates with its parent through events, from simple click callbacks to complex form submission payloads. Declaring emits explicitly serves two purposes: it documents the component’s event API, and it enables Vue to distinguish between custom events and native DOM events on the root element. The TypeScript generic syntax provides the best developer experience with full type inference on the emitted payload.

Declare emits with runtime validation syntax.

<script setup>
const emit = defineEmits({
  // No validation
  click: null,

  // Validate payload shape
  submit: (data) => {
    return data.name && data.email
  },

  // Emit with multiple args
  change: (value, oldValue) => typeof value === 'number'
})

function handleSubmit() {
  emit('submit', { name: 'Alice', email: '[email protected]' })
}

function handleChange(val, old) {
  emit('change', val, old)
}
</script>

Validator functions return true for valid payloads. Vue logs a warning in development when validation fails. The validators are runtime only — they don’t provide TypeScript type inference on the calling side.

TypeScript Generic Syntax

Full type safety with TypeScript.

<script setup lang="ts">
interface User {
  id: number
  name: string
  email: string
}

const emit = defineEmits<{
  submit: [user: User]            // Single arg
  cancel: []                      // No args
  change: [value: number, old: number]  // Multiple args
  'update:modelValue': [value: string]  // v-model support
}>()

function handleSubmit(user: User) {
  emit('submit', user) // TypeScript checks the payload type
}

function handleUpdate(val: string) {
  emit('update:modelValue', val) // Enables v-model on this component
}
</script>

The object syntax uses event names as keys and tuple types as values. TypeScript will error if you call emit('submit', wrongType). The update:modelValue convention enables using v-model on the component.

Two-Way Binding with v-model

Implement v-model support using defineProps + defineEmits.

<!-- NumberInput.vue -->
<template>
  <input
    type="number"
    :value="modelValue"
    @input="emit('update:modelValue', Number($event.target.value))"
  />
</template>

<script setup lang="ts">
defineProps<{ modelValue: number }>()
const emit = defineEmits<{ 'update:modelValue': [value: number] }>()
</script>
<!-- Parent.vue -->
<template>
  <!-- v-model works because of the prop/emit convention -->
  <NumberInput v-model="quantity" />
</template>

<script setup>
import { ref } from 'vue'
const quantity = ref(0)
</script>

v-model on a component is syntactic sugar for :modelValue="quantity" @update:modelValue="quantity = $event". Matching the prop name and emit name to this convention enables v-model.

Best Practice Note

In CoreUI Vue components we always declare defineEmits with TypeScript types — it makes the component’s public API self-documenting and prevents event name typos that cause silent failures. Always declare emits even when no validation is needed, as it tells Vue the event is intentional and suppresses warnings about unknown event listeners. See how to define props in Vue 3 with defineProps for the complementary input declaration pattern.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to validate an email address in JavaScript
How to validate an email address in JavaScript

JavaScript printf equivalent
JavaScript printf equivalent

How to get element ID in JavaScript
How to get element ID in JavaScript

How to Use Bootstrap Tooltip in Vue 3 – The Right Way with CoreUI
How to Use Bootstrap Tooltip in Vue 3 – The Right Way with CoreUI

Answers by CoreUI Core Team