colinhacks / zod

TypeScript-first schema validation with static type inference
https://zod.dev
MIT License
33.09k stars 1.15k forks source link

z.date({ coerce: 'iso' }) #3643

Open mmkal opened 2 months ago

mmkal commented 2 months ago

hi - I find z.date({ coerce: true }) very useful when using with trpc or another tool that uses JSON to cross an i/o boundary. Because, it forces the client to use a Date value - which is then serialized via its toJSON method into an ISO string and correctly converted back to a Date on the other side. So you get nice Date types on either side of the boundary.

But a not-ideal effect of using that trick is that it will also accept values like null and 0 which both parse to 1970-01-01T00:00:00.000Z, so it's a bit dangerous.

So suggestion here is to change coerce: boolean to coerce: boolean | 'iso', then update this block: https://github.com/colinhacks/zod/blob/9257ab78eec366c04331a3c2d59deb344a02d9f6/src/types.ts#L1798-L1800

An easy change to that block which should give the right results:

if (this._def.coerce === 'iso') {
  const coerced = typeof input.data === 'string' ? new Date(input.data) : null;
  if (coerced && coerced.toISOString() === input.data) {
    input.data = coerced;
  }
} else if (this._def.coerce) {
  input.data = new Date(input.data);
}

This just makes sure that the ISO string exactly matches the parsed Date's ISO string, but it could also use a regex or some other ISO string validation technique.