vazco / uniforms

A React library for building forms from any schema.
https://uniforms.tools
MIT License
1.94k stars 239 forks source link

[ZOD] Implement logic to handle Zod.discriminatedUnion #1292

Open dj-fiorex opened 10 months ago

dj-fiorex commented 10 months ago

Hel everyone, i'm willig to use Zod.discriminatedUnion to create an object that based on the value of a property has a different shape. i tried with this simple example:

const columnSchema = z.discriminatedUnion("columnType", [
  z.object({
    columnType: z.literal("slider"),
    columnContent: z.object({
      title: z.string(),
      imageUrl: z.string(),
    }),
  }),
  z.object({
    columnType: z.literal("image"),
    columnContent: z.object({
      title: z.string(),
      description: z.string(),
      link: z.string(),
      imageUrl: z.string(),
    }),
  }),
]);

 const schema = z.object({
  invertColumns: z.boolean(),
  settings: z.object({
    desktop: z.object({ ratio: z.string() }),
    mobile: z.object({ ratio: z.string() }),
  }),
  column1: columnSchema,
  column2: columnSchema,
});

but i received an error:

Uncaught Invariant Violation: Field "column1" has an unknown type
    at invariant (http://localhost:8282/dist/vendors-node_modules_digitalrock_skin-styles-utils_dist_Container_js-node_modules_digitalrock-9a1109.bundle.js:86287:15)
    at ZodBridge.getType (http://localhost:8282/dist/vendors-node_modules_digitalrock_skin-styles-utils_dist_Container_js-node_modules_digitalrock-9a1109.bundle.js:104862:57)
    at ZodBridge.memoized [as getType] (http://localhost:8282/dist/vendors-node_modules_digitalrock_skin-styles-utils_dist_Container_js-node_modules_digitalrock-9a1109.bundle.js:97861:23)
    at useField (http://localhost:8282/dist/vendors-node_modules_digitalrock_skin-styles-utils_dist_Container_js-node_modules_digitalrock-9a1109.bundle.js:106747:38)
    at AutoField (http://localhost:8282/dist/vendors-node_modules_digitalrock_skin-styles-utils_dist_Container_js-node_modules_digitalrock-9a1109.bundle.js:106495:86)
    at renderWithHooks (http://localhost:8282/dist/main.bundle.js:59943:18)
    at mountIndeterminateComponent (http://localhost:8282/dist/main.bundle.js:62769:13)
    at beginWork (http://localhost:8282/dist/main.bundle.js:64007:16)
    at HTMLUnknownElement.callCallback (http://localhost:8282/dist/main.bundle.js:48903:14)
    at Object.invokeGuardedCallbackDev (http://localhost:8282/dist/main.bundle.js:48952:16)
invariant @ browser.js:38
getType @ ZodBridge.js:196
memoized @ memoize.js:62
useField @ useField.js:21
AutoField @ createAutoField.js:11
renderWithHooks @ react-dom.development.js:14985

I think that the error come from getType of the ZodBridge because there isn't an implementation of discriminatedUnion

Is there any plan on supporting this? i think i could have some time to work on this if you think it could help others also. Or if you have a different implementation for my use case please let me know!

Thanks

Monteth commented 10 months ago

Hello @dj-fiorex, Thank you for pointing it out - currently, we don't have support for it in the Zod schema. There is something very similar in JSON schema: https://uniforms.tools/docs/api-bridges/#note-on-allofanyofoneof, but it doesn't work in all cases. I think it is an important feature, and we want it to be supported, but we didn't have it on the board until now.

We would love to receive help from the community, so if you find the time, we encourage you to create a PR with this change. Remember that we can always help if you encounter any difficulties.