So here is a basic example of modern Vue 3 props declaration with <script setup lang="ts">
with mandatory name
and optional age
:
// <script setup lang="ts">
defineProps<{
name: string,
age?: number
}>()
// </script>
Here is the same declaration, but with age
having default value:
// <script setup lang="ts">
withDefaults(defineProps<{
name: string,
age?: number
}>(), {
age: 20
})
// </script>
My main question is: is there a way to incorporate validators in this new syntax? Or whenever I need to add a validator, I need to roll back to the old syntax, i.e.:
// <script setup lang="ts">
defineProps({
age: {
type: Number,
validator(value: number) => value > 0
}
})
// </script>
I've found similar topics where some suggest to use both generic types and pass parameters to defineProps like this:
// <script setup lang="ts">
defineProps<{
age: number
}>({
age: {
validator(value: number) => value > 0
}
})
// </script>
But this approach doesn't work and immediately falls with the error: defineProps has both a type-only props and an argument.
(eslintvue/valid-define-props)
The incompatibility between runtime and type declarations is unequivocally stated in current documentation:
defineProps
ordefineEmits
can only use either runtime declaration OR type declaration. Using both at the same time will result in a compile error.
Additionally, there is no way to pass a props validator using types declaration, it can only be done using runtime declaration:
defineProps({
age: {
type: Number,
validator(value: number) => value > 0,
default: 20
}
})
Side note: if the property receives an invalid value, Vue will not silently apply the valid default value. Instead, it will throw a warning about receiving an invalid value. This is intended behavior.
The default value is only applied when the property is not provided (or the provided expression compiles to undefined
).