Search code examples
yupjoi

How to validate alternatives in Yup?


I'm used to Joi validation syntax, but right now trying to migrate some code to Yup syntax.

In Joi, I used to do this:

  field: Joi.alternatives().try(
    Joi.number(),
    Joi.string(),
  )

This makes the field either a number or a string.

How to achieve that using Yup?


Solution

  • UPDATE:

    I created a better solution, which works for any number of whatever schema types you pass!

    First you define a method called oneOfSchemas

    yup.addMethod(yup.MixedSchema, "oneOfSchemas", function (schemas) {
      return this.test(
        "one-of-schemas",
        "Not all items in ${path} match one of the allowed schemas",
        (item) =>
          schemas.some((schema) => schema.isValidSync(item, { strict: true }))
      );
    });
    

    Then you use it as follows:

    title: yup
      .mixed()
      .oneOfSchemas([
        yup
          .object()
          .noUnknown()
          .shape(SchemaObject1),
        yup
          .object()
          .noUnknown()
          .shape(SchemaObject2),
      ]),
    

    Inspired by https://gist.github.com/cb109/8eda798a4179dc21e46922a5fbb98be6

    This is the only way I found, please correct me if I'm wrong or if you have better answers:

    field: yup.lazy((val) => (isNaN(val) ? yup.string() : yup.number()))
    

    This however won't work when the alternatives are objects, which I would like to find a solution for.