Skip to the solution
EasyFrontend6 min read

What are props in Vue and how do you validate them?

1.0k views

The problem

Question presented to candidate: "You are writing a reusable PriceTag component for our shop. It needs a label, an amount, a currency from a fixed list, optional tags and an on-sale flag. How do you declare those props, how would you validate them, and what actually happens when a parent passes something invalid?"

What a strong answer should cover:

  • Props are the inputs of a component: data passed down from the parent, read-only inside the child (one-way data flow).
  • Declaration forms: an array of names, an object with options, or (in <script setup> with TypeScript) a type.
  • Validation options: type (constructor or array of constructors), required, default (a factory function for objects and arrays) and a custom validator (which also receives all props since Vue 3.4).
  • Boolean casting: a boolean prop that is present with no value is true, absent is false.
  • Failed validation only logs a development warning; the component still renders, and production builds skip the checks entirely.
  • camelCase in JavaScript, kebab-case in templates.

Clarifying questions expected:

  • "Is the project in TypeScript? Then most of this moves to compile-time types."
  • "Should an invalid currency fall back to a default, or is a dev warning enough?"

Code / implementation expected: Yes. A props declaration with at least a required prop, a default and a custom validator.

  • vue
  • props
  • components

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read Β· 10 sections

Read the code

VueProp validation: type, required, default factory, validator and Boolean casting
<script setup>
import { ref, defineComponent, h } from "vue";

// Options-object props with validation. Every rule below only runs in development builds.
const PriceTag = defineComponent({
  props: {
    label: { type: String, required: true },
    amount: { type: Number, default: 0 },
    currency: {
      type: String,
      default: "USD",
      validator: (value) => ["USD", "EUR", "INR"].includes(value),
    },
    // Objects and arrays need a factory, so every instance gets its own copy
    tags: { type: Array, default: () => [] },
    // Boolean props are cast: present with no value means true, absent means false
    onSale: Boolean,
    // The validator also receives the other props (Vue 3.4+)
    discount: {
      type: Number,
      default: 0,
      validator: (value, props) => value <= props.amount,
    },
  },
  setup(props) {
    return () =>
      h("li", `${props.label}: ${props.amount - props.discount} ${props.currency}` +
        ` | onSale=${props.onSale} | tags=${JSON.stringify(props.tags)}`);
  },
});

const price = ref(25);
</script>

<template>
  <ul>
    <PriceTag label="Book" :amount="price" on-sale :tags="['paper']" />
    <PriceTag label="Pen" />
    <PriceTag :amount="'12'" currency="GBP" :discount="99" />
  </ul>
</template>
VueChild.vue: Boolean casting order and read-only props
<script setup>
const props = defineProps({
  count: { type: Number, required: true },
  flag: [Boolean, String],
  label: [String, Boolean],
  items: { type: Array, default: () => [] },
});
function bump() {
  props.count++; // not allowed: props are readonly
}
</script>
<template><button @click="bump">{{ count }} flag={{ JSON.stringify(flag) }} label={{ JSON.stringify(label) }}</button></template>

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 4 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextEasy

What are Vue directives? Give common examples.

Continue