DEV Community

cn-2k
cn-2k

Posted on

Working with props declaration in Vue 3 + Typescript

In this post I will show you'll how to work with component props in Vue 3 + Composition API using <script setup>, there's few ways to work with it, let's take a look!

Using the defineProps() macro we can declare props like:

1 - Array of strings

<script setup>
const props = defineProps(['foo'])

console.log(props.foo)
</script>
Enter fullscreen mode Exit fullscreen mode

2 - Object syntax

<script setup>
const props = defineProps({
  title: String,
  likes: Number
})

console.log(props.title)
</script>
Enter fullscreen mode Exit fullscreen mode

2.1 - Object syntax with details

<script setup>
const props = defineProps({
     title: {
         type: String,
         required: true,
         default: '---'
     },
})
</script>
Enter fullscreen mode Exit fullscreen mode

Working with props in Vue 3 with Typescript

Let's see how to declare props in Vue 3 script setup with Typescript:

1 - Type-based declaration

<script setup lang="ts">
defineProps<{
  title?: string
  likes: number
}>()
</script>
Enter fullscreen mode Exit fullscreen mode

In this case we have title and likes props, title is optional and likes is an required prop.

2 - Type-based declaration with default props values

<script setup lang="ts">
 withDefaults(defineProps<{
   title?: string
   likes: number,
 }>(), {
     // here we have default values
     title: '---',
 })
</script>
Enter fullscreen mode Exit fullscreen mode

3 - Advanced types with PropType

For use PropType interface you need to import it from vue:

<script setup lang="ts">
import { type PropType } from 'vue'

export interface Book {
  title: string
  author: string
  year: number
}

const props = defineProps({
    book: {
        type: Object as PropType<Book>,
        required: true,
    }
})
</script>
Enter fullscreen mode Exit fullscreen mode

That's it!

If you want to read and learn more details about component props declaration, please make sure to visit the Vue 3 official documentation about props.

See'ya!

Top comments (8)

Collapse
 
dennisschmock profile image
Dennis Schmock

Being a big fan of script setup approach, I find your example useful.

However, since you are using Typescript, I would suggest you change the approach a bit.

This would, from my perspective be a more readable, maintainable, and less bloated if you actually embrace the power of Generics in Typescript.

My approach from your example would be:

export interface Book {
  title?: string
  author: string
  year: number
}

interface Props {
  book: Book
}

const props = defineProps<Prop>();
Enter fullscreen mode Exit fullscreen mode

If you want a prop to be optional:

interface Props {
  myOptionalProp?: Book
}
Enter fullscreen mode Exit fullscreen mode

And with default props:

const props = withDefaults(defineProps<Props>(), {
  title: "My default title"
})
Enter fullscreen mode Exit fullscreen mode

Usually I would name my prop interface to mirror the component I use it in:

interface BookItemProps {
 //my props here
}

defineProps<BookItemProps>();
Enter fullscreen mode Exit fullscreen mode

The above examples does the exact same thing as it does in your examples, but we do not have to define type and required for each field in the props, since that is being handled perfectly by Typescript and Vue

Collapse
 
cn-2k profile image
cn-2k

Amazing approach, Dennis!

I'll make sure to follow this way of work with props and typescript for now, much more readable and maintainable.

Thanks for the contribuition!

Collapse
 
idmick profile image
Mick

Nice, can you also give an example of how to do this when you have a validator for a prop? I can't figure out how to do this with this syntax...

Collapse
 
dennisschmock profile image
Dennis Schmock

If you try to give me an example for custom validator you would use for a prop, I'll show you how I would do it.

Collapse
 
danargh profile image
Danargh

Thankyou for the idea

Collapse
 
saanglee profile image
saanglee

Thanks!!! This post is really helpful :)

Collapse
 
cesswhite profile image
César Armando

Thanks for the post, is very helpful

Collapse
 
cn-2k profile image
cn-2k

You're welcome! Thanks :)