There's no way to specify schema as one of two types: https://github.com/jquense/yup/issues/321
However you can dynamically return a schema with Yup.lazy(): https://github.com/jquense/yup/issues/647. If the img_url begins with 'data', return schema for data URI using Yup.string().matches(), otherwise, return schema for url with Yup.string().url()
You can find the gist and discussion about data URI regex here
This should work:
const validationSchema = Yup.object().shape({
img_url: Yup.lazy((value) =>
/^data/.test(value)
? Yup.string()
.trim()
.matches(
/^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)$/i,
'Must be a valid data URI',
)
.required()
: Yup.string().trim().url('Must be a valid URL').required(),
),
});
Note: I've added trim() so that you can have extra whitespaces around the URL or the data URI for img_url to still be considered valid. Also, I made img_url required so that it is considered invalid if empty. You might or might not want this based on your use case.
Here's a version without trim() or required():
validationSchema={Yup.object({
img_url: Yup.lazy((value) =>
/^data/.test(value)
? Yup.string().matches(
/^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)$/i,
'Must be a valid data URI',
)
: Yup.string().url('Must be a valid URL'),
)