JAVASCRIPT
Type-Safe Props and Emits in Vue 3 Composition API
Implement robust, type-safe component communication in Vue 3 using the Composition API with TypeScript for defining props and custom events (`emits`).
// ChildComponent.vue
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
interface Props {
message: string;
count?: number;
isActive: boolean;
}
// Define props with TypeScript interface
const props = defineProps<Props>();
interface Emits {
(event: 'update:message', value: string): void;
(event: 'itemClicked', id: number): void;
}
// Define emits with TypeScript interface
const emit = defineEmits<Emits>();
const handleClick = () => {
emit('itemClicked', 123);
emit('update:message', 'New message from child!');
};
</script>
<template>
<div class="child-component">
<h3>Child Component</h3>
<p>Prop Message: {{ props.message }}</p>
<p>Prop Count: {{ props.count ?? 'N/A' }}</p>
<p>Prop Is Active: {{ props.isActive }}</p>
<button @click="handleClick">Emit Event</button>
</div>
</template>
// ParentComponent.vue
<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent!');
const parentCount = ref(5);
const parentIsActive = ref(true);
const handleItemClicked = (id: number) => {
console.log(`Item with ID ${id} was clicked in child.`);
};
</script>
<template>
<div>
<h1>Parent Component</h1>
<p>Parent Message: {{ parentMessage }}</p>
<ChildComponent
:message="parentMessage"
:count="parentCount"
:is-active="parentIsActive"
@update:message="parentMessage = $event"
@item-clicked="handleItemClicked"
/>
</div>
</template>
How it works: This example demonstrates how to define props and custom events (emits) in Vue 3 using the Composition API with TypeScript for type safety. In `ChildComponent.vue`, `defineProps<Props>()` uses a TypeScript interface to specify the expected types and optionality of incoming props. Similarly, `defineEmits<Emits>()` defines the custom events the component can emit, including their payload types. The parent component then passes data via props and listens for these custom events, enabling robust and predictable component communication with compile-time type checking.