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?
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>()