Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to type props in Vue with TypeScript

Typing props in Vue with TypeScript ensures components only receive valid data, provides IDE autocompletion for prop usage, and catches type errors at compile time rather than runtime. As the creator of CoreUI with Vue and TypeScript development experience since 2014, I type every prop in CoreUI Vue components to prevent incorrect usage and generate accurate API documentation automatically. There are two approaches: PropType with the Options API or defineProps generics with <script setup> — the latter is cleaner and more expressive for TypeScript projects. Both produce the same runtime behavior; the difference is developer experience and type inference quality.

Type props using defineProps with a TypeScript interface in <script setup>.

<script setup lang="ts">
interface Address {
  street: string
  city: string
  country: string
}

interface UserCardProps {
  name: string
  email: string
  age?: number           // Optional prop
  role: 'admin' | 'user' | 'viewer'  // Union type
  address?: Address      // Optional nested object
  tags?: string[]        // Optional array
  onDelete?: () => void  // Optional callback
}

const props = defineProps<UserCardProps>()

// props.name is string
// props.role is 'admin' | 'user' | 'viewer'
// props.address?.city is string | undefined
</script>

<template>
  <div class="user-card">
    <h3>{{ name }}</h3>
    <p>{{ email }}  {{ role }}</p>
    <p v-if="address">{{ address.city }}, {{ address.country }}</p>
    <div>
      <span v-for="tag in tags" :key="tag" class="badge">{{ tag }}</span>
    </div>
  </div>
</template>

TypeScript marks properties without ? as required. Calling <UserCard /> without the name, email, or role prop causes a TypeScript compile error.

Adding Default Values with withDefaults

<script setup lang="ts">
interface ButtonProps {
  label: string
  variant?: 'primary' | 'secondary' | 'danger'
  size?: 'sm' | 'md' | 'lg'
  disabled?: boolean
  loading?: boolean
}

const props = withDefaults(defineProps<ButtonProps>(), {
  variant: 'primary',
  size: 'md',
  disabled: false,
  loading: false
})
</script>

withDefaults adds runtime default values while preserving TypeScript types. Without withDefaults, optional props are T | undefinedwithDefaults removes undefined from the type for props with defaults.

PropType for Options API

Use PropType to type props when using the Options API.

import { defineComponent, PropType } from 'vue'

interface Product {
  id: number
  name: string
  price: number
}

export default defineComponent({
  props: {
    product: {
      type: Object as PropType<Product>,
      required: true
    },
    quantity: {
      type: Number,
      default: 1
    },
    categories: {
      type: Array as PropType<string[]>,
      default: () => []
    },
    onAddToCart: {
      type: Function as PropType<(product: Product) => void>
    }
  },

  setup(props) {
    // props.product is typed as Product
    // props.categories is typed as string[]
    console.log(props.product.name)
  }
})

Object as PropType<Product> tells TypeScript the Object type validator corresponds to the Product interface. Without PropType, props.product would be typed as object, losing all property type information.

Best Practice Note

In CoreUI Vue components we exclusively use defineProps<Interface>() for <script setup> components because it gives better TypeScript inference than PropType without any extra typing. Export the props interface from the component file so parent components can import and reuse the type. See how to define props in Vue 3 with defineProps for the runtime validation aspects of defineProps.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to dynamically add, remove, and toggle CSS classes in React.js
How to dynamically add, remove, and toggle CSS classes in React.js

How to Manage Date and Time in Specific Timezones Using JavaScript
How to Manage Date and Time in Specific Timezones Using JavaScript

What is globalThis in JavaScript?
What is globalThis in JavaScript?

How to Open Link in a New Tab in HTML?
How to Open Link in a New Tab in HTML?

Answers by CoreUI Core Team