Vue 3 script setup prop validation typescript

Viewed 1682

I'm trying to replace my Vue 2 options API props object code with Vue 3 script setup syntax in typescript.

Existing:

type: {
  type: String,
  default: 'button',
  validator: (prop) => ['button', 'submit', 'reset'].includes(prop)
}

I have this so far:

<script lang="ts" setup>
interface Props {
  type?: string;
}

const props = withDefaults(defineProps<Props>(), { type: 'button' });
</script>

but I can't find any info on how to handle prop validators in the script setup syntax

5 Answers

You can use in defineProps the same structure as in Options API. (DOCS)

<script lang="ts" setup>
  type Type = 'button' | 'submit' | 'reset';

  interface Props {
    type: Type;
  }

  const props = defineProps<Props>({ 
    type: {
      type: String,
      default: 'button',
      validator: (prop: Type) => ['button', 'submit', 'reset'].includes(prop)
    }
  });
</script>

Following up @Titan 's answer I like to write it in a way in which I get direct access to the prop in the script.

<script setup lang="ts">
type Type = 'button' | 'submit' | 'reset';

const { type } = withDefaults(defineProps<{
  type?: Type
}>(),{
  type: 'button'
})
//As it is already deconstructed, you can use it as `type` instead of `props.type`
</script>

Although I would recommend changing the prop name from type to something different since typescript might misunderstand the prop name for an actual type declaration.

For those also arriving from Google, and since the Vue docs aren't very clear on this, you can do a straight conversion using the Vue 2 style options format as well:

const props = defineProps({
  type: {
    type: String,
    default: 'button',
    validator: (prop) => ['button', 'submit', 'reset'].includes(prop)
  }
})

I believe I've worked it out, still new to typescript but this should be the equivalent (will be validated in typescript rather than vue runtime)

interface Props {
  type?: 'button' | 'submit' | 'reset';
}

I end up with this at the end ‍♂️

<script lang="ts" setup>
  import type { PropType } from 'vue';
  export type Type = 'button' | 'submit' | 'reset';

  export interface Props {
    type: Type;
  }

  defineProps({ 
    type: {
      type: String as PropType<Type>,
      default: 'button',
      validator: (prop: Type) => ['button', 'submit', 'reset'].includes(prop)
    }
  });
</script> 
Related