zod icon indicating copy to clipboard operation
zod copied to clipboard

[Feature suggestion] A way to chain/pipe validations

Open webNeat opened this issue 1 year ago • 4 comments

Hello,

First of all, thank you for making and maintaining this awesome library.

I started using zod to validate forms on a frontend project, and found myself doing things like:

const FormData = z.object({
  age: z.string().transform((x, ctx) => {
    const value = parseInt(x)
    if (isNaN(value) || value < 0) {
      ctx.addIssue({code: z.ZodIssueCode.custom, message: 'should be a positif integer'})
      return z.NEVER
    }
    return value
  }),
  worked_days_in_month: z.string().transform((x, ctx) => {
    const value = parseInt(x)
    if (isNaN(value) || value < 0 || value > 31) {
      ctx.addIssue({code: z.ZodIssueCode.custom, message: 'should be an integer between 1 and 31'})
      return z.NEVER
    }
    return value
  }),
})

Since all values coming from the HTML inputs are strings, I have to validate them using z.string then use .transform to convert them to numbers and do additional validation.

I think it will be easier if after converting them to numbers, I could chain them to a z.number with some additional checks, something like:

const FormData = z.object({
  age: z.string().transform(x => parseInt(x)).chain(z.number().int().min(0)),
  worked_days_in_month: z.string().transform(x => parseInt(x)).chain(z.number().int().min(0).max(31)),
})

So my suggestion is to add a method .chain (or .pipe or other name ...) that behaves as follows:

const a: ZodType // with types: _input = A and _output = B
const b: ZodType // with types: _input = B and _output = C

const c = a.chain(b) // gives a ZodType with _input = A and _output = C

Let me know if this is something you would be interested in adding to the library, I can try to make a PR for it if you agree.

webNeat avatar Oct 27 '22 23:10 webNeat