Vue prop type validation object schema Vue prop type validation object schema vue.js vue.js

Vue prop type validation object schema


The problem with a TypeScript only solution is that it only checks types at compile-time and is limited to type checking. This won't help you at run-time if you're passing in dynamic objects or need additional data constraints.

I recently found a library that for run-time validation but it wasn't well suited for use with Vue 2.x or the Babel compiler as it used JavaScript reserved words as function names. So I forked the project, refactored the code to support both TypeScript and JavaScript and specifically added an asSuccess() function to support validation of VueJS object properties.

So if you had a TypeScript interface like ...

interface Pet {  name: string;  species: string;  age?: number;  isCute?: boolean;}

You could validate a Pet property using either JavaScript or TypeScript code as ...

import { tObject, tString, tNumber, tBoolean, optional } from 'runtime-validator'// VueJs componentexport default {  name: 'MyPet',  props: {    pet: {      type: Object,      required: true,      validator: tObject({        name: tString(),        species: tString(),        age: optional(tNumber()),        isCute: optional(tBoolean())      }).asSuccess    }  },  ...}

tObject() will accept objects having additional fields to those defined. If you need to disallow additional fields, use tObjectStrict().

You can also add value constraints ...

export default {  name: 'MyPet',  props: {    pet: {      type: Object,      required: true,      validator: tObject({        name: tString(),        species: oneOf("cat", "dog", "bird"),        age: optional(range(0, 150)),        isCute: optional(tBoolean())      }).asSuccess    }  },  ...}

It has much broader application than properties as it can also be used for data validation in unit testing, vuex actions and mutations, server-side payloads and more.

Full documentation is here ...


You should definitely use TypeScript. What you are expecting is called "type annotation", you will get a quick overview on TypeScript Quick start tutorial.

Vue.js has TypeScript support out of the box. See https://vuejs.org/v2/guide/typescript.html


I'm going to piggyback off of @Clorichel's answer because TypeScript is doing wonders for me. It's a late answer, but I've been needing the same thing as you: object schema validation, not just simply "is this prop a string or number?". TypeScript offers the usage of an interface, which contractually bounds the shape of an object to that type (interface). So if I have

interface GreetingSchema {  message: string;}

doing let myGreeting = <GreetingSchema>{ message: 1234 } is going to throw the error

Type '{ message: number; }' cannot be converted to type 'GreetingSchema'.  Types of property 'message' are incompatible.    Type 'number' is not comparable to type 'string'.

To extend this a little further by integrating it with Vue, you can leverage interfaces during compile time to perform object schema validation on component props that are passed down from parents to children. For example, a child Greeting component (Greeting.vue) can be coupled with the object schema for the props that will be passed to it (I'm using a nested schema to spice things up):

<template>  <div>    {{message}}{{      speaker        ? ` from ${speaker.firstName}${            speaker.lastName ? ` ${speaker.lastName}` : ''          }        : ''    }}  </div></template><script lang="ts">export default {  name: 'greeting',  props: ['message', 'speaker'],}interface SpeakerSchema { // this will be a nested schema  firstName: string;  lastName?: string; // last name of speaker is optional}export interface GreetingSchema {  message: string;  speaker?: SpeakerSchema; // speaker is optional}</script>

You may then import the Greeting component along with its corresponding GreetingSchema into the parent to ensure that whenever the parent passes its greetingData down to a child Greeting with v-bind, greetingData is going to be bound by the shape defined in GreetingSchema

<template>  <div>    This greeting is being displayed from the parent:    <greeting v-bind="greetingData" />   </div></template><script lang="ts">import Greeting, {GreetingSchema} from './Greeting' // path to Greeting.vueexport default {  name: 'parent',  components: {Greeting},  data () {    return {      greetingData: <GreetingSchema>{        message: 'hi there',        speaker: {          firstName: 'myFirstName',          lastName: 1234 // error because it's not a string        },      }    }  },}</script>

What's awesome is that the errors can be shown directly in your text editor with the right extensions, even in .vue files. I'm using Visual Studio Code, which has TypeScript support out of the box, with the vetur extension. What's even awesomer is that TypeScript's home page features a presentation in which TypeScript is used with Vue's single file components!