Last active
June 5, 2023 11:30
-
-
Save cb109/8eda798a4179dc21e46922a5fbb98be6 to your computer and use it in GitHub Desktop.
YUP: Validate that items in an Array match one of multiple allowed Schemas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The yup library has no builtin way to check if items in an array | |
* match one or more defined shapes, we can only check against a set of | |
* whitelisted values using yup.array().oneOf([..]). | |
* | |
* Using yup.addMethod() and yup.mixed().test() however we can pretty | |
* much add any custom validation we want. The function below allows to | |
* make validation pass for array items of different shapes. | |
*/ | |
const assert = require('assert'); | |
const yup = require('yup'); | |
// Please note this method is sync. An async version would return a Promise. | |
yup.addMethod(yup.array, 'oneOfSchemas', function(schemas) { | |
return this.test( | |
'one-of-schemas', | |
'Not all items in ${path} match one of the allowed schemas', | |
items => items.every(item => { | |
return schemas.some(schema => schema.isValidSync(item, {strict: true})) | |
}) | |
) | |
}) | |
// Usage example below. Run like: $ nodejs yup_array_oneOfSchemas.js | |
const Beer = yup.object().noUnknown().shape({ | |
'alcoholConcentration': yup.number(), | |
}) | |
const Water = yup.object().noUnknown().shape({ | |
'sparkling': yup.boolean(), | |
}) | |
const Crate = yup.object().noUnknown().shape({ | |
// Any item in the array must match either the Beer or Water schema. | |
'bottles': yup.array().oneOfSchemas([Beer, Water]), | |
}) | |
const crate = { | |
bottles: [ | |
{'sparkling': true}, | |
{'alcoholConcentration': 5}, | |
] | |
} | |
assert.strictEqual(Crate.isValidSync(crate, {strict: true}), true) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is how we finally did it, we created a new method called 'requiredByAssertion', which allows us to require some fields based on another field value assertion.
Following the last example: