Vue 3 Defineprops

Posted on  by admin

Modified2 months ago. From within a setup method, using defineProps I can use. which allows me to have the type Tab[] on props.tabs. however, if I want to specify ComponentObjectPropsOptions, I believe the syntax is. but with that syntax I lose my type on props.tabs :(.

44 gold badges3636 silver badges6060 bronze badges.

Not the answer you're looking for? Browse other questions tagged typescriptvue.js or ask your own question.

6060 bronze badges. You'll need to use the PropType utility to type cast your array.

22 gold badges1515 silver badges2727 bronze badges.

2727 bronze badges.


Implicit return

We can also remove the return at the end:all the top-level bindings declared inside a script setup (and all imports)are automatically available in the template.So here ponyImageUrl and clicked are available without needing to return them.

This is the same for the components declaration!Importing the Image component is enough,and Vue understands that it is used in the template:we can remove the components declaration.


We’re nearly there: we now need to migrate the props and emits declarations.


Vue offers a defineProps helper that you can use to define your props.It’s a compile-time helper (a macro), so you don’t need to import it in your code:Vue automatically understands it when it compiles the component.

defineProps returns the props:

defineProps receives the former props declaration as a parameter.But we can do even better for TypeScript users!

defineProps is generically typed:you can call it without a parameter,but specify an interface as the “shape” of the props.No more horrible Object as PropType to write!We can use proper TypeScript types,and add ? to mark a prop as not required 😍.

We lost a bit of information though.In the previous version, we could specify that isRunning had a default value of false.To have the same behavior, we can use the withDefaults helper:

The last remaining syntax to migrate is the emits declaration.


Vue offers a defineEmits helper, very similar to the defineProps helper.defineEmits returns the emit function:

Or even better, with TypeScript:

The full component declaration is 10 lines shorter.Not a bad reduction for a ~30 lines component!It’s easier to read, and plays better with TypeScript.It does feel a bit weird to have everything automatically exposed to the template,without writing return though, but you get used to it.


Closed by default and defineExpose

There is a more subtle difference between the two ways to declare components:a script setup component is “closed by default”.This means other components don’t see what’s defined inside the component.

For example, the Pony component can access the Image component(by using refs, as we’ll see in a following chapter).If Image is defined with defineComponent,then everything returned by the setup function is also visible for the parent component (Pony).If Image is defined with script setup,then nothing is visible for the parent component.Image can pick what is exposed by adding a defineExpose({ key: value }) helper.Then the exposed value will be accessible as key.

This syntax is now the recommended way to declare your components,and it’s awesome to use!

Our ebook, online training and training are up-to-date with these changes if you want to learn more!

Please enable JavaScript to view the comments powered by comments powered by Disqus