Hi.
I wonder why, empty strings, are considered valid as for email and url methods, but invalid for the rest of the methods?
I've read this issue https://github.com/jquense/yup/issues/667 and I think the user who posted it has a point.
yup.object().shape({
email: yup.string().email(),
name: yup.string().min(3).max(100),
taxId: yup.string().uppercase().length(9).matches(/^[0-9]{8}[A-Z]$/),
}).validateSync({
email: '',
name: '',
taxId: ''
});
IMHO the above code should return that the object is valid, cause none of the properties are reqquired.
But it doesn't. Both name and taxId are invalid.
Maybe create another method like empty or notEmpty for strings? (like required/notRequired or nullable)
yup.object().shape({
email: yup.string().empty().email(),
name: yup.string().empty().min(3).max(100),
taxId: yup.string().empty().uppercase().length(9).matches(/^[0-9]{8}[A-Z]$/),
}).validateSync({
email: '',
name: '',
taxId: ''
});
We ran to this issue also. There is code written for url and email validations to behave like this https://github.com/jquense/yup/blob/master/src/string.js#L100 and https://github.com/jquense/yup/blob/master/src/string.js#L108
removing excludeEmptyString from url and email would make more sense in my mind. For example const contactDetails = yup.object({
name: yup.string().required(),
email: yup
.string()
.email()
.notRequired(),
}) would behave as Joi validation. Email is optional but if it's defined then it must be a email. Empty string is still a definition.
Don't know if there are other implications though. url, and email validations seem the only ones using this behaviour as defaults. It could also be that signature would be changed to same as with string.matches https://github.com/jquense/yup#stringmatchesregex-regex-options--message-string-excludeemptystring-bool--schema and default to false
@hixus removing excludeEmptyString would make those strings always required, since the empty string will fail the regex. The reason empty strings are excluded is precisely to allow you to use required here. It also means you can provide clearer errors, instead of "Invalid email address" for an empty input
I removed the excludeEmptyString and tried yup.string().email().validateSync(undefined). It accepted undefined so the change didn't make it always required.
As the issue keeps coming up what would be the preferred solution for rule "valid email or undefined"? I could add it to the readme. For orm, it's easy to strip away undefined values but with empty strings it does not know if the empty string is actually wanted.
For any wanderer in the future; If you want to have .min(n) for strings that will check for min length _but_ will also allow you a 0 length string (because it's not a required field) you can emulate this behavior with:
string().test(
'min8',
'This must be at least 8 characters long',
value => (value.trim().length > 0 ? value.length >= 8 : true)
)
Changing 8 with your number of choice.
Most helpful comment
For any wanderer in the future; If you want to have
.min(n)for strings that will check for min length _but_ will also allow you a 0 length string (because it's not a required field) you can emulate this behavior with:Changing
8with your number of choice.