Yup is a great validation library, and is extremely flexible when it comes to make adjustments to how your validation should work. It can handle async validation however we'll only focus on synchronous here.
Dates are generally the most complicated to deal with. There are so many intricacies to deal with when validating. If your date value is being stored as a string then we'll need to add in parsing logic to fix that.
By default yup
will pass the value to new Date()
however depending on the format of your date string that may or may not work.
If the way you're storing your date value doesn't work when passing to new Date()
then you'll need to setup a custom transform.
When setting up a yup validation it can work on a single value or an object. To validate an object we'd use the object
import from yup
like so import { object } from "yup";
Our validation schema would then be setup to mirror what the object structure will be to validate.
const schema = object({ //object keys for validation go here });
So if we were to do a required name, and email our validation would look something like this. We'd need to import string
from yup first.
const schema = object({ name: string().required(), email: string().email().required(), });
Additionally there are many built ins supplied by yup for the specific types, and additionally you can add more if necessary. Thankfully for dates Yup provides a min
and max
. However as mentioned before depending your date is being stored to validate then you may need to transform the date first before.
The transform function will receive both the value
and the originalValue
. The value
in the case of dates would be what was returned from the value after being passed to new Date
. The originalValue
will be what was passed to new Date
. So if it were a string before then our value
would be a Date
and the originalValue
would be a string
.
date().transform((value, originalValue) => {});
This matters since any date being passed in could be a string, or date and you need to decide how each should be treated. There are some helpers that yup
provides however for date work I decided to use date-fns
.
We first check if the originalValue
(could be string or date) is a date. If it is we use it, otherwise we attempt to parse the date using date-fns
parse method.
The parse
method will return either a new Date or an Invalid Date. If an Invalid Date is returned then our validation will fail. Otherwise if a proper Date is returned then the other assertions will use the Date value to validate your data.
With parse
we specify the format and in this case we would expect a value such as year-month-date
, but if your date string value is something else than you'll need to adjust that to match.
import { parse, isDate } from "date-fns"; function parseDateString(value, originalValue) { const parsedDate = isDate(originalValue) ? originalValue : parse(originalValue, "yyyy-MM-dd", new Date()); return parsedDate; }
The one thing to note when using our transform call is that even the today
new Date()
is passed into the transform. So this is why it's crucial for our parse function to check if the value is a date already.
import { date, object } from "yup"; const today = new Date(); const schema = object({ birthday: date().transform(parseDateString).max(today), }); const isValid = schema.validateSync({ birthday: "2020-02-02", });
Then we can call one of Yups validate methods, and it all works flawlessly.