When you're building Vue 3 apps with TypeScript, defining props carefully is important. But if you're not careful, you might find yourself copy-pasting the same props over and over across components.

A much better way is to extend prop types. This keeps your components simple, consistent, and type-safe.

Let's walk through a clean, simple example.

The problem

Suppose you have a basic button component with a few common props like label and disabled.

Later, you want to build a specialized button, like a "LinkButton", that behaves a little differently but still needs all the base props.

Instead of copying all the props, you can extend them.

Step 1: Create the BaseButton

<!-- BaseButton.vue -->
<script setup lang="ts">
export interface BaseButtonProps {
  label: string;
  disabled?: boolean;
}

const props = defineProps<BaseButtonProps>();
</script>

<template>
  <button :disabled="props.disabled">{{ props.label }}</button>
</template>

This is a simple button that takes a label and an optional disabled state.

Step 2: Create a specialized Button by extending props

Now, you want a LinkButton that acts like a button but also takes a href prop (for the link URL).

You can extend the base props like this:

<!-- LinkButton.vue -->
<script setup lang="ts">
import BaseButton, { BaseButtonProps } from './BaseButton.vue';

interface LinkButtonProps extends BaseButtonProps {
  href: string;
}

const props = defineProps<LinkButtonProps>();
</script>

<template>
  <a :href="props.href">
    <BaseButton v-bind="props" />
  </a>
</template>

✅ All the BaseButtonProps (label, disabled) are automatically included.
LinkButton adds its own href prop.
✅ You don't have to repeat or duplicate the base props.

Why this pattern is powerful

  • No duplication: You define common props once and reuse them everywhere.
  • Type safety: If you change BaseButtonProps, the changes propagate automatically.
  • Clear code: Each specialized component focuses only on its differences.
  • Easy maintenance: Your components stay small, predictable, and consistent.

Quick Visual

Without Extending With Extending
Repeat all props manually Inherit props automatically
High risk of mistakes Compiler catches missing/invalid props
Hard to maintain over time Easy to update in one place

Conclusion

If you're building reusable Vue 3 components with TypeScript, extending your prop interfaces is one of the simplest and best ways to keep your code clean, scalable, and easy to maintain.

Whenever you notice yourself copying prop definitions between components — stop and think:
➡️ Should I extend instead?

Most of the time, the answer will be yes.