2

I have the following code example from a tutorial and I try to figure out how to use a validator in a similar way as the example, using the script setup, typescript and the composition API.

props: {
    image: {
      type: String,
      default: require("@/assets/default-poster.png"),
      validator: propValue => {
        const hasImagesDir = propValue.indexOf("@/assets/") > -1;
        const listOfAvailableExt = [".jpeg", ".jpg", ".png"];
        const isValidExt = listOfAvailableExt.some(ext =>
          propValue.endsWith(ext)
        );
        return hasImagesDir && isValidExt;
      }
    }
  }

I know how to declare the type and the default value but I couldn't find a way to use a validator. Is there any function to validate the different properties?

interface Props {
  image: string
}

const props = withDefaults(defineProps<Props>(), {
  image: require("@/assets/default-poster.png")
});
rgutt
  • 43
  • 5
  • Did you check the docs? https://vuejs.org/guide/components/props.html#prop-validation . defineProps accepts the same `props` object. It's unknown what is withDefaults in your case. – Estus Flask Feb 13 '22 at 17:19

1 Answers1

5

In <script setup>, only the function argument of defineProps() supports validator (as of Vue 3.2.31). The function argument has the same type as the props option:

defineProps({
  image: {
    type: String,
    default: require("@/assets/default-poster.png"),
    validator: (propValue: string) => {
      const hasImagesDir = propValue.indexOf("@/assets/") > -1;
      const listOfAvailableExt = [".jpeg", ".jpg", ".png"];
      const isValidExt = listOfAvailableExt.some(ext =>
        propValue.endsWith(ext)
      );
      return hasImagesDir && isValidExt;
    }
  }
})

Note you can't mix the type-only props declaration with the function argument of defineProps(), so any other props would also have to be converted into the option form.

Alternatively, you could implement your own prop validation:

<script setup lang="ts">
interface Props {
  image: string
}

const props = withDefaults(defineProps<Props>(), {
  image: require("@/assets/default-poster.png")
});

if (import.meta.env.DEV /* process.env.NODE_ENV === 'development' */) {
  const isValidImage = (propValue: string) => {
    const hasImagesDir = propValue.indexOf("@/assets/") > -1;
    const listOfAvailableExt = [".jpeg", ".jpg", ".png"];
    const isValidExt = listOfAvailableExt.some(ext =>
      propValue.endsWith(ext)
    );
    return hasImagesDir && isValidExt;
  }

  if (!isValidImage(props.image)) {
    console.warn(`invalid image: ${props.image}`)
  }
}
</script>
tony19
  • 125,647
  • 18
  • 229
  • 307