GithubHelp home page GithubHelp logo

Comments (5)

peguerosdc avatar peguerosdc commented on September 25, 2024 1

@abuaboud exactly, that doesn't work either.

I couldn't fully resolve it with TypeBox and ended up having to manually validate the more complex parts of my schema, directly appending the results to the output of react-hook-form (which is not coupled to zod @matjaeck because you can use other resolvers).

If you're using this library too and are okay with the trade-offs, you'll need to set up a custom resolver like this:

import { Resolver } from "react-hook-form";
import { Static, Type } from "@sinclair/typebox";

import { typeboxResolver } from "@hookform/resolvers/typebox";

const schema = Type.Object({...});
type SchemaType = Static<typeof schema>;

export const myResolver: Resolver<SchemaType> = async (
  data,
  context,
  options,
) => {
  const baseResult = await typeboxResolver(schema)(data, context, options);
  return {
    values: baseResult.values,
    errors: {
      ...baseResult.errors,
      // This is the result of my custom validation:
      rootField: {
        validatedField: {
          type: "required",
          message:
            "This is my custom error to show up for field 'rootField.validatedField'",
        },
      },
    },
  };
};

Optionally, if you need to call it without react-hook-form's hook, you can do:

const data: SchemaType = {...};
const errors = (await myResolver(
  data,
  {},
  { fields: {}, shouldUseNativeValidation: undefined },
)).errors;

Would be great to have a library that supports all of this natively AND is as fast and efficient as TypeBox. I hope this feature can be included, although I understand if it's beyond the intended scope.

Btw: you could pull this off with zods refinements, but its low performance was freezing my vscode when trying to resolve the types.

from typebox.

matjaeck avatar matjaeck commented on September 25, 2024

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.)

from typebox.

Lonli-Lokli avatar Lonli-Lokli commented on September 25, 2024

@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'})

from typebox.

abuaboud avatar abuaboud commented on September 25, 2024

Hi @Lonli-Lokli

I did this, but if you have a union of objects, the typeboxResolver will only show an error for the union, not the specific fields, as @peguerosdc described in point 3.

@peguerosdc, did you manage to find any solutions? Our codebase relies heavily on TypeBox, and we would love to use it in React as we are transitioning from Angular to React.

from typebox.

sinclairzx81 avatar sinclairzx81 commented on September 25, 2024

@peguerosdc @Lonli-Lokli @abuaboud @matjaeck Hi! Apologies for the delay in reply here (I've been exceptionally busy with other project as of late)

So, I may convert this issue into a discussion as I think there is value in talking about better custom errors in TypeBox. Currently the following is TypeBox's answer to custom error messages.

import { SetErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/errors'

SetErrorFunction(params => params.schema.errorMessage ?? DefaultErrorFunction(params))

const T = Type.Union([
  Type.Literal('A'),
  Type.Literal('B'),
  Type.Literal('C'),
], {
  errorMessage: 'Expected A, B, C'
})

console.log(Value.Errors(T, 'D').First()) // { message: 'Expected A, B, C' }

While the above works, I do think TypeBox could be doing a better job with Union error messages. Unfortunately things do get very sophisticated when working with nested Unions of Objects (where errors may originate deep within the Union), and at this point in time, there is no obvious / concise / ordered way to handle them. Consider

const T = Type.Union([
  Type.Object({ a: Type.Number(), x: Type.Number() }),
  Type.Object({ a: Type.Number(), y: Type.Number() }),
  Type.Object({ a: Type.Number(), z: Type.Number() })
])

Value.Errors(T, { a: 1 }).First() // what should the first error be?
                                  // should this generate a invalid object error(s)?
                                  // should x, y, z be generated as sub property errors?
                                  // should all errors be wrapped in a outer error?
                                  //  - is there potential for DoS attack collecting all errors?

This said, the above structures are very common (and I expect they would be quite common in forms). It's just that in order to produce something better, the above questions need some consideration so I know what to build :)

Hope this brings a bit of insight into where things are currently at. Will convert to discussions for now, happy to field any questions on this, as well as take on suggestions as to how things could be improved.

Cheers all!
S

from typebox.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.