I’m using Vue 3 and TS 4.4. I’ve got a component that defines its prop types with defineProps
. When I add a call to defineEmits
, VS Code starts telling me my props
variable doesn’t exist in the component template. Here’s the source code:
<script setup lang="ts"> import { defineProps, defineEmits, VueElement, defineComponent } from "vue"; const emit = defineEmits<{ "update:checked": boolean; }>(); const props = defineProps<{ label?: VueElement | string; checked?: boolean; }>(); </script> <template> <label> <input type="checkbox" :checked="props.checked" @change="(event) => emit('update:checked', (event.target as any)?.checked)" /> {{ props.label }} </label> </template>
And a couple of screenshots to better show what I’m seeing in VS Code. This is after adding defineEmits
:
And this is without defineEmits
:
What is the correct way to define types for both props and emits?
Advertisement
Answer
The defineEmits<T>()
generic argument is essentially a TypeScript interface that defines only functions, which receive a specific event name and optional arguments:
interface Emits { (e: __EVENT1_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]]...): void (e: __EVENT2_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]]...): void }
Examples:
// as inline type const emits = defineEmits<{ (eventName: 'hover', hovering: boolean): void (eventName: 'changed', newValue: number, id: string): void }>()
// as interface interface Emits { (eventName: 'hover', hovering: boolean): void (eventName: 'changed', newValue: number, id: string): void } const emits = defineEmits<Emits>()
// as type alias type Emits = { (eventName: 'hover', hovering: boolean): void (eventName: 'changed', newValue: number, id: string): void } const emits = defineEmits<Emits>()
For your update:checked
event, the code should look similar to the following:
// as inline type const emits = defineEmits<{ (e: 'update:checked', checked: boolean): void }>()
// as interface interface Emits { (e: 'update:checked', checked: boolean): void } const emits = defineEmits<Emits>()
// as type alias type Emits = { (e: 'update:checked', checked: boolean): void } const emits = defineEmits<Emits>()