Published on

Using WithDefaults to Shorten Prop Declaration

Using WithDefaults to Shorten Prop Declaration

When using Vue 3 with Typescript, you might have noticed that prop declaration can get a bit verbose. You have to declare the type of the prop and then set the default value. This can get a bit tedious when you have a lot of props, and can be even worst when you need to assign default values. Luckily, there is a helper function that can help you shorten the prop declaration.

In the example below, we have a simple profile image component.

Let's take a look at how we would declare the props the "traditional" way.

<script setup lang="ts">
import type { PropType } from 'vue'
const props = defineProps({
  source: {
    type: String as PropType<string>,
    default: '/profile.png',
  },
  alt: {
    type: String as PropType<string>,
    default: 'Profile Photo',
  },
  large: {
    type: Boolean as PropType<boolean>,
    default: true,
  },
})
</script>

<template>
  <img
    :src="source"
    :alt="alt"
    class="rounded-full bg-zinc-100 object-cover dark:bg-zinc-800"
    :class="large ? 'h-16 w-16' : 'w-9 h-9'"
    :sizes="large ? '4rem' : '2.25rem'"
  />
</template>

As you can see, we have to declare our props and assign our types all within the same statement, which can get very long.

Now with this next approach, lets break out the prop declaration into a separate interface (this is optional, but I find it helps with readability). And then we can use the withDefaults helper to assign our default values.

<script setup lang="ts">
export interface Props {
  source?: string;
  alt?: string;
  large?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  source: "/profile.png",
  alt: "Profile Photo",
  large: true
});
</script>

<template>
  <img
    :src="source"
    :alt="alt"
    class="rounded-full bg-zinc-100 object-cover dark:bg-zinc-800"
    :class="large ? 'h-16 w-16' : 'w-9 h-9'"
    :sizes="large ? '4rem' : '2.25rem'"
  />
</template>

As you can see, we can now declare our props in a much more readable way. And we can also assign our default values in a much more readable way too.

You can still declare props this way, even if you don't need to assign default values. I like to create an interface for my props, so its easier to see what props are available to the component.