Yup how to validate mandatory fields on null object

Viewed 6779

I have a problem regarding the validation of mandatory fields which are properties of a (possibly) null object.

Here is an example schema :

object().shape({
   catalog: {
      brand: string().required()
   }
})

If I try to validate the following object against this schema, I get the expected error : brand is required. From what I understood, there is a default value created for undefined object which mimics the shape of the object in the schema. This is the behavior I expected and what I want.

{ catalog: undefined }

// "catalog.brand is a required field"

But in my case, I don't receive an object with undefined, but with null. And I can't figure out how to manage the same result with a null value.

{ catalog: null }

// No error on catalog.brand

Manually casting null to undefined is out of the question as there is a good reason why I receive null.

Here is a codesandbox which reproduces my use case :

https://codesandbox.io/s/yup-playground-tbfcj

I would really appreciate a bit of help on this, thanks :)

3 Answers

The solution is to include both nullable() and required() to the shape.

Example

const requiredOption = Yup.object()
  .shape({
    value: Yup.string(),
    label: Yup.string(),
  })
  .nullable()
  .required('This field is required.');

Here's a less mindbending way to do it than the other answer. This allows you to keep the required directive on the subfield whether or not the parent schema/field containing it is empty at validation time.

yup.object().shape({
  field: yup.object().shape({
    subfield: string().required(),
  }).default(undefined),
});

// Or...

yup.object().shape({
  field: yup.object().shape({
    subfield: string().required(),
  }).default(null).nullable(),
});

One difference between the two is that when you validate data over each of these schemas and field is missing, if you also pass in stripUnknown, in the first case the field will be totally removed from the validated result, but in the second case the field will still show up but with value null.

Try adding strict() on your object schema

object().shape({
   catalog: {
      brand: string().required()
   }
}).strict();
Related