Advanced Props, Slots, and Emits in Vue 3
vuepropsslotsemits
Bright Amoah
Frontend Developer
|
Friday 1st August, 2025
|
9 minutes mins to read
|
Share this blog

Vue 3's component communication system—props, slots, and emits—has become more powerful and type-safe with TypeScript. But many developers struggle with advanced patterns, especially when building reusable components. This guide will help you master these features using best practices.
Defining Typed Props
Use defineProps with TypeScript interfaces for full type safety:
<script setup lang="ts">
interface ButtonProps {
label: string;
color?: "primary" | "secondary";
disabled?: boolean;
}
defineProps<ButtonProps>();
</script>
Default Values and Destructuring
Destructure props to set default values:
<script setup lang="ts">
interface CardProps {
title: string;
subtitle?: string;
}
const { title, subtitle = "Default subtitle" } = defineProps<CardProps>();
</script>
Typed Emits
Use defineEmits for type-safe custom events:
<script setup lang="ts">
const emit = defineEmits<{
(e: "submit", payload: { value: string }): void;
(e: "cancel"): void;
}>();
function onSubmit() {
emit("submit", { value: "Hello" });
}
</script>
Advanced Slots with TypeScript
Declare slot props for full type inference:
<script setup lang="ts">
interface Item {
id: number;
name: string;
}
defineSlots<{
default(props: { item: Item }): any;
footer(): any;
}>();
</script>
<template>
<div>
<slot :item="{ id: 1, name: 'Vue' }" />
<slot name="footer" />
</div>
</template>
Best Practices
- Always use TypeScript for props, emits, and slots.
- Use destructuring for default values.
- Prefer explicit slot typing for reusable components.
- Document all events and slot props in your component docs.
Wrap-Up
Mastering props, slots, and emits with TypeScript unlocks the full power of Vue 3 for building robust, reusable components. For more, see the official Vue docs.