Yup
Tags: schema, javascript, object
Published: 2019-11-24 21:03:10

**[Yup](https://github.com/jquense/yup) is a simple object schema validator I came across recently. It is inspired by [Joi](https://github.com/hapijs/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`.


```js
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...

```js
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.

```js
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.

```js
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](https://www.linkedin.com/in/szib77/) | [Github](https://githib.com/szib) | [Instagram](https://www.instagram.com/szib77/)