Using VueTypes Validators
VueTypes is a collection of prop validators. Each validator is basically a factory function returning an object (validator object) compatible with Vue prop validation.
Differently from simple Vue prop validation objects, VueTypes prop validator objects provide some additional chainable properties and methods to control things like required
and default values.
Validators can be imported as named functions from vue-types
:
import Vue from 'vue'
import { number, oneOf } from 'vue-types'
export default {
props: {
id: number().isRequired,
status: oneOf(['open', 'close']).def('open'),
},
}
Validators can be categorized in two groups:
- Native Validators
- Custom Validators
Native Validators
Native validators come with:
- a
def(any)
method to assign a default value for the current prop. The passed-in value will be validated against the type configuration in order to prevent invalid values. - a
isRequired
flag to set therequired: true
property. - a
validate(function)
method to set a custom validator function (not available ininteger
andsymbol
).
import { number } from 'vue-types'
const numProp = number()
// numProp === { type: Number}
const numPropCustom = number().def(10)
// numPropCustom === { type: Number, default : 10}
const numPropRequired = number().isRequired
// numPropRequired === { type: Number, required : true}
const numPropRequiredCustom = number().def(10).isRequired
// numPropRequiredCustom === { type: Number, default: 10, required : true}
const gtTen = (num) => num > 10
const numPropGreaterThanTen = number().validate(gtTen)
// numPropGreaterThanTen === { type: Number, validator: (num) => num > 10 }
UPDATING DEFAULT VALUES
You can unset any previously defined default value by passing undefined
to .def()
const type = string().def('hello')
// { type: String, default: 'hello' }
type.def(undefined)
// { type: String }
Note: Executing .def(undefined)
on boolean or mixed-boolean types, explicitly sets the default
property to undefined
:
const type = bool().def(true)
// { type: Boolean, default: true }
type.def(undefined)
// { type: Boolean, default: undefined }
const mixedType = oneOfType([bool(), string()])
// { type: [Boolean, String] }
mixedType.def(undefined)
// { type: [Boolean, String], default: undefined }
any
Validates any type of value. This validator should be used sparingly and can be an escape hatch for props with unknown values.
props: {
myProp: any(),
}
TYPESCRIPT HINT
In TypeScript, you can specify a type constraint other than any
:
props: {
// type is `any`
myPropAny: any(),
// type is `unknown`
myPropUnknown: any<unknown>(),
}
array
Validates that a prop is an array primitive.
props: {
users: array(),
}
TYPESCRIPT HINT
In TypeScript, you can specify the type of array items as type argument:
props: {
// array of strings
users: array<string>(),
// specify the allowed array items
fruits: array<'apple' | 'pear'>()
}
Note: this signature will validate the prop at compile-time only. For runtime validation use arrayOf
TIP
Vue prop validation requires Array props to provide default value as a factory function. array().def()
accepts both factory functions and arrays. In the latter case, VueTypes will convert the value to a factory function for you.
bool
Validates boolean props.
props: {
enabled: bool()
}
undefined
AS DEFAULT VALUE
Executing .def(undefined)
on boolean or mixed-boolean types, explicitly sets the default
property to undefined
:
const type = bool().def(true)
// { type: Boolean, default: true }
type.def(undefined)
// { type: Boolean, default: undefined }
const mixedType = oneOfType([bool(), string()])
// { type: [Boolean, String] }
mixedType.def(undefined)
// { type: [Boolean, String], default: undefined }
func
Validates that a prop is a function.
props: {
onClick: func()
}
TYPESCRIPT HINT
You can constrain the function signature passing it as type argument:
props: {
// expects an event handler
onClick: func<(event: Event) => void>()
}
number
Validates that a prop is a number.
props: {
length: number()
}
TYPESCRIPT HINT
You can constrain the number value with a type argument:
props: {
// union type
length: number<1 | 2 | 3>()
}
Note: this signature will validate the prop at compile-time only. For runtime validation use oneOf
.
integer
Validates that a prop is an integer.
props: {
age: integer()
}
TYPESCRIPT HINT
Because integer()
inherits from number()
, you can constrain its value with a type argument as well (see above for details).
object
Validates that a prop is an object.
props: {
user: object()
}
TYPESCRIPT HINT
You can specify the shape of the object as type argument:
interface User {
ID: number
username: string
}
// ...
props: {
// restrict the object to the properties of User
user: object<User>()
}
Note: this signature will validate the prop at compile-time only. For runtime validation use shape
TIP
Vue prop validation requires Object props to provide default value as a factory function. object().def()
accepts both factory functions and plain objects. In the latter case, VueTypes will convert the value to a factory function for you.
string
Validates that a prop is a string.
props: {
username: string()
}
TYPESCRIPT HINT
You can constrain the string value with a type argument:
enum Fruits {
Apple = 'Apple',
Pear = 'Pear',
}
props: {
// string enum
users: string<Fruits>(),
// union type
fruits: string<'apple' | 'pear'>()
}
Note: this signature will validate the prop at compile-time only. For runtime validation use oneOf
.
symbol
Validates that a prop is a Symbol.
props: {
uniq: symbol()
}
nullable
Validates that a prop is null.
props: {
isNull: nullable()
}
WARNING
This validator does not come with any flag or method. It can be used with oneOfType
to make a required prop nullable.
props: {
stringOrNull: oneOfType([string(), nullable()]).isRequired
}
Use this validator sparingly. Nullable props are not encouraged in Vue components, so please consider reviewing your strategy.
Custom Validators
Custom validators are a special kind of factory function useful to describe complex validation requirements. By design custom validators:
- don't have a
validate
method - have a
.def()
method to assign a default value on the current prop - have an
isRequired
flag to set therequired: true
property
const oneOfPropDefault = oneOf([0, 1]).def(1)
// oneOfPropDefault.default === 1
const oneOfPropRequired = oneOf([0, 1]).isRequired
// oneOfPropRequired.required === true
const oneOfPropRequiredCustom = oneOf([0, 1]).def(1).isRequired
// oneOfPropRequiredCustom.default === 1
// oneOfPropRequiredCustom.required === true
instanceOf
Validates that a prop is an instance of a JavaScript constructor. This validator uses JavaScript's instanceof
operator.
class User {
// ...
}
props: {
user: instanceOf(User)
}
oneOf
Validates that a prop is one of the provided values.
props: {
genre: oneOf(['action', 'thriller'])
}
TYPESCRIPT HINT
To constrain the allowed values at compile-time use const assertions on the passed-in array or union types (see caveats):
props: {
genre: oneOf(['action', 'thriller'] as const)
}
// mostly same as
type Genre = 'action' | 'thriller'
props: {
genre: oneOf<Genre>(['action', 'thriller'])
}
oneOfType
Validates that a prop is an object that could be one of many types. Accepts as inner validators an array of JavaScript constructors, Vue.js props validation objects and VueTypes validators objects.
props: {
// Either a string, an integer or an instance of the User class
theProp: oneOfType([String, integer(), instanceOf(User)])
}
This validator can be used to compose complex validation logic including native types, specific values (using oneOf
) and null
(using nullable
):
props: {
// Either a number (of pixels), a keyword, or null
// translates to: number | 'fit-content' | 'auto' | null
width: oneOfType([
Number,
oneOf(['fit-content', 'auto'] as const),
nullable(),
])
}
TYPESCRIPT HINT
You can constrain the expected types passing them as type argument:
type User = { name: string; id: string }
props: {
// string or instance of User
theProp: oneOfType<string | User>([String, Object])
}
Constraints can be set on the inner validators as well:
type User = { name: string; id: string }
props: {
// same as above
theProp: oneOfType([String, object<User>()])
}
arrayOf
Validates that a prop is an array of a certain type. Accepts JavaScript constructors, Vue.js props validation objects and VueTypes validators objects.
props: {
//accepts: ['my', 'string']
//rejects: ['my', 1]
theProp: arrayOf(String),
// accepts an array of objects
userList: arrayOf(object())
}
TIP
Prop Validators are composable. For example, to validate an array that can contain both strings and numbers you can use arrayOf
and oneOfType
:
props: {
// an array containing both strings and numbers
collection: arrayOf(oneOfType([String, Number]))
}
In TypeScript, composition can be used together with type arguments to constrain the final prop type:
type User = { name: string; id: string }
props: {
// an array containing both arrays of strings and User object instances
collection: arrayOf(oneOfType([array<string>(), object<User>()]))
}
objectOf
Validates that a prop is an object with values of a certain type. Accepts JavaScript constructors, Vue.js props validation objects and VueTypes validators objects.
props: {
//accepts: {name: 'John', surname: 'Doe'}
//rejects: {name: 'John', age: 30}
userData: objectOf(String)
}
shape
Validates that a prop is an object taking on a particular shape. Shape properties value can be JavaScript constructors, Vue.js props validation objects or VueTypes validators objects.
Note that:
- You can set the properties of the shape as
required
but you cannot use.def()
. - You can use
.def()
to set a default value for the shape itself. - Like
array
andobject
, you can pass to.def()
either a factory function returning an object or a plain object.
props: {
// default value = {name: 'John'}
//accepts: {name: 'John', age: 30, id: 1}
//rejects: {name: 'John', age: 30} -> missing required `id` key
//rejects: {name: 'John', age: 'wrong data', id: 1} -> age is not a number
userData: shape({
name: String,
age: integer(),
id: integer().isRequired,
}).def(() => ({ name: 'John' }))
}
TYPESCRIPT HINT
You can constrain the shape with a type argument:
interface User {
name?: string
age?: number
id: number
}
// ...
props: {
userData: shape<User>({
name: String,
age: integer(),
id: integer().isRequired,
}).def(() => ({ name: 'John' }))
}
Loose shape matching
By default shape
will reject objects containing properties not defined in the shape. To allow partial matching use the loose
flag:
export default {
props: {
//accepts: {name: 'John', id: 1}
//rejects: {name: 'John', id: 1, age: 30} --> age not defined in the shape
userData: shape({
name: String,
id: integer().isRequired,
}),
//accepts: {name: 'John', id: 1}
//accepts: {name: 'John', id: 1, age: 30} --> loose matching
userDataLoose: shape({
name: String,
id: integer().isRequired,
}).loose, // <-- loose flag
},
}
custom
Validates prop values against a custom validation function.
function minLength(value) {
return typeof value === 'string' && value.length >= 6
}
// ...
props: {
username: custom(minLength)
}
//accepts: 'arandomusername'
//rejects: 'user', 1
Note that the passed-in function name will be used as the custom validator name in warnings.
You can pass a validation error message as second argument as well:
function minLength(value) {
return typeof value === 'string' && value.length >= 6
}
// ...
props: {
theProp: custom(minLength, 'theProp is not a string or is too short')
}
TYPESCRIPT HINT
In TypeScript, you can specify the prop type with a type argument:
function minLength(value) {
return typeof value === 'string' && value.length >= 6
}
// ...
props: {
// theProp is a string
theProp: custom<string>(minLength)
}
Utilities
VueTypes exposes some useful utility functions that can be used to extend the library functionalities.
validateType
Checks a value against a type definition.
Accepts the following arguments:
validator
: A JavaScript constructor or VueTypes validator objectvalue
: The value to check[silent=false]
: Toggle error console logging
If silent === false
the function will return a boolean. If silent === true
it will return true
if the check succeeds else it will return an error message.
import { validateType, arrayOf } from 'vue-types'
// VueTypes validator object
const isArrayOfStrings = arrayOf(String)
validateType(isArrayOfStrings, ['hello', 'world']) // true
validateType(isArrayOfStrings, ['hello', 1]) // false
// Native string constructor
validateType(Number, 10) // true
// returns an error message on failure
validateType(String, 10, false) // 'value "10" should be of type "string"`
toType / toValidableType
Convert an object compatible with Vue.js prop validation to a VueTypes validator object.
See Standalone custom validators for more details.
fromType
Creates a new validator object from a previously defined one.
See Inheriting from existing validators for more details.
createTypes
Returns a namespaced collection of validators.
See Custom namespaced instance for more details.