colinhacks / zod

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

Add an option to all checks (.min(), .url(), .regex(), ...) to abort early #1606

Open DanielBreiner opened 1 year ago

DanielBreiner commented 1 year ago

In some cases, it might be desirable to abort early in any of the type specific validations - checks - like .min, .url, .regex and so on. An example of this being useful is when they validate a parameter later used in an async refine (#1605), so without aborting early, the async refine is executed with an invalid input. Currently, you can work around this by implementing these checks yourself using superRefine, but it's unnecessarily tedious and verbose. A much simpler way would be to add a fatal field to the checks' message parameter.

ElYaiko commented 1 year ago

Yes, it could be something like:

  await schema.parseAsync(input, {
    fatalOnError: true
  });

And in the zodError.formErrors it could return the errors like:

{
  _errors: [],
  name: { _error: "String must contain at least 3 character(s)" },
  lastName: { _error: "Invalidated by API call." }
}

It's useful when you show only one error per field on the client-side.

ElYaiko commented 1 year ago

Yes, it could be something like:

  await schema.parseAsync(input, {
    fatalOnError: true
  });

And in the zodError.formErrors it could return the errors like:

{
  _errors: [],
  name: { _error: "String must contain at least 3 character(s)" },
  lastName: { _error: "Invalidated by API call." }
}

It's useful when you show only one error per field on the client-side.

I made a custom modification in the meanwhile that does this: https://github.com/ElYaiko/zod

I had to publish it at npm too because I had problems to install the build version from the repo, you can install it as zod-abort-failed

Hope this helps somebody with this issue too :)

andrew-sol commented 1 year ago

This is a feature any validation library should have. I see 2 possible options here:

I like the implementation in Laravel, see https://laravel.com/docs/9.x/validation#stopping-on-first-validation-failure

An example for Zod:

{
  // if the value is null, superRefine won't be executed here since the field is not optional
  name: z.string().bail().superRefine(...)

  // if the first superRefine fails (added any issues), the second one won't be executed
  text: z.string().bail().superRefine(...).superRefine(...)
}
KikoCosmetics commented 1 year ago

Bail looks good.

abdurahmanshiine commented 2 months ago

+1