[Feature request]: Add date-string to date parsing flag
Feature description
This package is proving itself quite useful when working with next-js form actions, but recently I came across a tiny roadbump when working with <input type="date">/ <input type="datetime-locale"> fields and I think it could be easily handled.
Say one has a data validation schema (zod in my case) with date fields, date-input elements will pass dates as ISO datestrings to FormData and server-side data validation will raise an error. One could use some coercion or transformation at the schema level, something like z.string().pipe( z.coerce.date() ) to overcome this, but this means the schema now expects a string value input and strays a little further from the expected Date value.
Maybe a new formData entry name prefix, here proposed as @, could be used by parse-nested-form-data to flag values that should be represented as Dates.
Ex.:
<form action={handleDate}>
<input type="datetime-locale" defaultValue={new Date().toISOString()} name="@start" />
</form>
export async function handleDate(formData: FormData) {
console.log(formData.get('@start')) // String
const parsed = parseFormData(formData);
console.log(parsed.start) // Date
}
For illustration, here's a draft implementation using transformEntry:
export const transformEntry: ParseFormDataOptions['transformEntry'] = (
[path, value],
defaultTransform
) => {
if (path.startsWith('@') && typeof value === 'string') {
return {
path: path.slice(1),
value: value.length ? new Date(value) : null,
};
}
return defaultTransform([path, value]);
};
Hi @iolyd,
Sorry for the late reply:
To handle date parsing in your schema, try using z.coerce.date() with Zod. This will allow you to transform the ISO date string into a Date object. Here's an example:
const schema = z.object({
start: z.string().pipe(z.coerce.date()),
end: z.coerce.date()
});
This way, you won't need a special formData entry prefix. The schema will parse the date string correctly into a Date object. See the zod docs for more info
Hope this helps!
Chris