'Validating array of different object shapes in yup

I am using formik for form validation and came across some problems in array validation. here is my form structure

{
 flow: [
  { text: "hello"
  },
  { input: "world"
  },
  { buttons: [
       'hi',
       'hello'
     ]
  }
 ]
}

I have to create validation schema for this. So the array may contain any of these objects.

I tried this,

export const validationSchema = yup.object().shape({
  flow: yup.array().of(
      yup.mixed().oneOf([
        {
          text: yup.string().required('Enter text'),
        },
        {
          buttons: yup.array().of(yup.string().required('Enter button title')),,
        },
        {
          input: yup.string()
          ),
        }
      ])
  ),
});

But am getting the following as formik error :

flow:[

"flow[0] must be one of the following values: [object Object], [object Object]",
"flow[1] must be one of the following values: [object Object], [object Object]"

]

How to solve this?



Solution 1:[1]

import { array, object, string, lazy } from 'yup';    

const differentObjectsArraySchema = array().of(lazy((item) => {
    const { type } = item;

    // any other condition
    if (type === 'text') {
        return object({
            text: string(),
        });
    }

    if (type === 'buttons') {
        return object({
            buttons: array(),
        });
    }

    if (type === 'input') {
        return object({
            input: string(),
        });
    }
}));

source: https://github.com/jquense/yup#yuplazyvalue-any--schema-lazy

Solution 2:[2]

If you look at the function signature for the oneOf method:

mixed.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema

The first parameter is an array of any, so any value will be valid within the array in the first parameter. It's the second message argument that can only be a string/function.

That being said, your code does look correct, so I'm not sure why you'd be receiving any errors. Maybe try adding a message argument and see if that will placate things. What is the exact error you're receiving, if there is one?

Solution 3:[3]

Maybe new custom schema type is a solution, but what about array schema with custom test function (with anyof logic)? In example below is just simple validity checking. https://codesandbox.io/s/yup-anyof-array-w0cww

Solution 4:[4]

I couldn't achieve this feature using Yup, I switched to joi and rewrite my two apps(it was very easy because the libraries have a lot of similarity between them) that I used Yup with them, joi support this feature out of the box along with other amazing features.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Chris B.
Solution 3 Kirill A. Khalitov
Solution 4 Omar Dulaimi