Yup is a simple object schema validator I came across recently. It is inspired by Joi, but smaller than that, so it is probably a better fit to the client side.
Install
npm install -S yup
It is recommended to install the types if you want to use it with TypeScript.
npm install -D @types/yup
Usage
First we can define a schema, then call validate
method to validate the passed data. It is asynchronous, it returns a Promise that going to be fulfilled with the data or rejected with ValidationError
.
validate
can take a second parameter: an options object. By default validation returns on the first error; if we need to all of the errors returned we must set abortEarly
to false
.
import { object, string } from 'yup';
const schema = yup.object().shape({
firstName: yup.string().required().max(10),
lastName: yup.string().required().max(10),
email: yup.string().email()
})
schema.validate({
firstName: 'Usagi',
lastName: 'Yojimbo',
email: 'usagi@yojimbo.jp'
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
// { firstName: 'Usagi',
// lastName: 'Yojimbo',
// email: 'usagi@yojimbo.jp' }
}).catch(err => {
console.log('err:', err.errors)
})
schema.validate({
firstName: 'Usagi Yojimbo',
//lastName: 'Yojimbo',
email: 'usagiyojimbo.jp'
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
// err: [ 'firstName must be at most 10 characters',
// 'lastName is a required field',
// 'email must be a valid email' ]
})
We can easily validate a number or a string...
const schemaNumber = yup.number().truncate('floor').positive().notOneOf([11,2,3])
schemaNumber.validate(-11.2).then(console.log).catch(err => console.error(err.errors))
// err: [ 'this must be a positive number' ]
schemaNumber.validate(11.2).then(console.log).catch(err => console.error(err.errors))
// err: [ 'this must not be one of the following values: 11, 2, 3' ]
schemaNumber.validate(1.6).then(console.log).catch(err => console.error(err.errors))
// 1
const schemaString = yup.string().min(2).max(5)
schemaString.validate('yup').then(console.log).catch(err => console.error(err.errors))
// yup
schemaString.validate('yupyup').then(console.log).catch(err => console.error(err.errors))
// [ 'this must be at most 5 characters' ]
schemaString.validate('').then(console.log).catch(err => console.error(err.errors))
// [ 'this must be at least 2 characters' ]
...but the yup shines the most when we have to do something more complicated. Let's say our object has to have student_id
key when the age
is under 18, otherwise we don't care about it.
const schema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required().min(1).max(100),
student_id: yup.string().when('age',{
is: age => age < 18,
then: yup.string().length(8).required()
})
})
schema.validate({
name: 'Usagi Yojimbo',
age: 22,
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
})
// valid: { name: 'Usagi Yojimbo', age: 22 }
schema.validate({
name: 'Usagi Yojimbo',
age: 17,
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
})
// err: [ 'student_id is a required field' ]
schema.validate({
name: 'Usagi Yojimbo',
age: 17,
student_id: '1234',
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
})
// err: [ 'student_id must be exactly 8 characters' ]
schema.validate({
name: 'Usagi Yojimbo',
age: 17,
student_id: '12345678',
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
})
// valid: { name: 'Usagi Yojimbo', age: 17, student_id: '12345678' }
We can even remove the unnecessary key.
const schema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required().min(1).max(100),
student_id: yup.string().when('age',{
is: age => age < 18,
then: yup.string().length(8).required(),
otherwise: yup.string().transform(x => undefined)
})
})
schema.validate({
name: 'Usagi Yojimbo',
age: 22,
student_id: '12345678',
}, {abortEarly: false}).then(valid => {
console.log('valid:', valid)
}).catch(err => {
console.log('err:', err.errors)
})
// valid: { age: 22, name: 'Usagi Yojimbo' }
I found yup very useful when I have to validate user inputs in React. I just update the form values in the state, call the validation when user types something and render the error messages next to the form elements.
Thanks for reading it. Happy coding. ❤
Top comments (2)
How do you return the field names for the errors? Right now it only returns the error text. I’m wanting the field name also.
and how are you doing data range validation ?