Yup: Making conditional validation in nested objects easier

Camilo García López
2 min readFeb 29, 2024

--

Sometimes when you are validating large and nested objects with yup and you wanna do a validation based (conditional validation) on a property of a parent of your current object, you realize that you can´t access to parents’ properties through schema.when() method.

Lets see an example:

import * as yup from "yup";
const yupWrongNestedSchema = yup.object({
user_type: yup.string().required(),
user: yup.object({
name: yup.string().required(),
password: yup.string().when("user_type", {
is: (val) => {
//this will output undefined
console.log(val);
return val === "admin";
},
then: (s) => s.required(),
otherwise: (s) => s,
}),
}),
});
//this must throw
try {
const data = {
user_type: "admin",
user: {
name: "admin",
},
};
yupWrongNestedSchema.validateSync(data);
} catch (e) {
console.log(e);
}

In the above example when we are trying to access to user_type property to work around the type of user and we just got an undefined.

So here is a simply solution to make this kind of schema

import * as yup from "yup";
const yupGoodNestedSchema = yup.object({
user_type: yup.string().required(),
user: yup.object({
name: yup.string().required(),
password: yup.string().when("$user_type", {
is: (val) => {
//this will output admin
console.log(val);
return val === "admin";
},
then: (s) => s.required(),
otherwise: (s) => s,
}),
}),
});
const data = {
user_type: "admin",
user: {
name: "admin",
},
};
//this must work

try {
yupGoodNestedSchema.validateSync(data, {
context: data,
});
} catch (e) {
console.log(e);
}

So how does it work?

Its very simply , when we add the prefix “$” to the key of the property that we are trying to access, we tell yup that the property will be taken from context, that “context” is an object that we send through yup config in the validate method

here is the codesandbox where you can try it out:

https://codesandbox.io/p/sandbox/yup-nested-validation-gmw39j

--

--