sinclairzx81 / typebox

Json Schema Type Builder with Static Type Resolution for TypeScript
Other
4.55k stars 147 forks source link

Custom paths for custom validation errors #893

Open peguerosdc opened 3 weeks ago

peguerosdc commented 3 weeks ago

Hi! Given the recent discussions on conditional validations (aka Refine) in the repo, I would like to share my use-case to expose one more need that is highly related and that I think would be a great addition to fully exploit their potential:

Context

I use typebox to do form validation using shadcn/ui + react-hook-form and I have been many times in the situation where I need to:

  1. Do conditional validation of complex schemas where the accepted values of one field(s) depend on another field(s)
  2. Give feedback to the user on why the form didn't pass the validation
  3. Give feedback to the user on which part of the form didn't pass the validation

How far can I get with typebox?

I have tried implementations with this Refine type and Unions and I am able to meet requirement 1, but not 2 and 3.

Both threads discuss about errors being too generic and provide a workaround that works for requirement 2 using SetErrorFunction, but still doesn't cover 3.

Trying to be more concrete: I need to not only customize the error message, but also the path to which the error is related. This would allow me to highlight the specific form fields in the UI to catch the user's attention. In fact, shadcn/ui already does it but depends on the path.

Based on what I have read in the repository I understand that this feature might not be considered soon, but if someday you think about Refine again (or any other more complex validation strategy), I hope you can consider this :)

matjaeck commented 2 weeks ago

You can already return custom error messages per field and different error messages per field. The way I solved this is to simply throw a custom error within the validation code you use inside of your Refine function. Just pass the field and the error message for each validation branch to your custom error and then wrap your call to Check in a try/catch clause. A typeguard function using instanceof will ensure you are catching your custom error and from there on you have all the information present in the custom error instance.

This approach works well for me, however I'm not using react-hook-form, as that lib ships with Zod and I prefer @sinclairzx81's lib.

(Please excuse the ping but I thought you might want to intervene in case this approach is an anti-pattern.)

Lonli-Lokli commented 1 week ago

@matjaeck That's not generic, I think the best way to accomplish this it to add 'errorMessage' to Type.String({ minLength: 10, errorMessage: 'Message too short'})