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:
JavaScript
x
24
24
1
<script setup lang="ts">
2
import { defineProps, defineEmits, VueElement, defineComponent } from "vue";
3
4
const emit = defineEmits<{
5
"update:checked": boolean;
6
}>();
7
8
const props = defineProps<{
9
label?: VueElement | string;
10
checked?: boolean;
11
}>();
12
</script>
13
14
<template>
15
<label>
16
<input
17
type="checkbox"
18
:checked="props.checked"
19
@change="(event) => emit('update:checked', (event.target as any)?.checked)"
20
/>
21
{{ props.label }}
22
</label>
23
</template>
24
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:
JavaScript
1
5
1
interface Emits {
2
(e: __EVENT1_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]] ): void
3
(e: __EVENT2_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]] ): void
4
}
5
Examples:
JavaScript
1
6
1
// as inline type
2
const emits = defineEmits<{
3
(eventName: 'hover', hovering: boolean): void
4
(eventName: 'changed', newValue: number, id: string): void
5
}>()
6
JavaScript
1
7
1
// as interface
2
interface Emits {
3
(eventName: 'hover', hovering: boolean): void
4
(eventName: 'changed', newValue: number, id: string): void
5
}
6
const emits = defineEmits<Emits>()
7
JavaScript
1
7
1
// as type alias
2
type Emits = {
3
(eventName: 'hover', hovering: boolean): void
4
(eventName: 'changed', newValue: number, id: string): void
5
}
6
const emits = defineEmits<Emits>()
7
For your update:checked
event, the code should look similar to the following:
JavaScript
1
5
1
// as inline type
2
const emits = defineEmits<{
3
(e: 'update:checked', checked: boolean): void
4
}>()
5
JavaScript
1
6
1
// as interface
2
interface Emits {
3
(e: 'update:checked', checked: boolean): void
4
}
5
const emits = defineEmits<Emits>()
6
JavaScript
1
6
1
// as type alias
2
type Emits = {
3
(e: 'update:checked', checked: boolean): void
4
}
5
const emits = defineEmits<Emits>()
6