DEV Community

Ivan Szebenszki
Ivan Szebenszki

Posted on

Yup

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. ❤

Say hello.
LinkedIn | Github | Instagram

Top comments (2)

Collapse
 
speck1990 profile image
Stephen Peck

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.

Collapse
 
speshov profile image
SPeshov

and how are you doing data range validation ?