typescriptvalidationvuejs3

Full props declaration (with defaults and validators) in Vue 3 + TypeScript + <script setup>


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)


Solution

  • The incompatibility between runtime and type declarations is unequivocally stated in current documentation:

    • defineProps or defineEmits 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).