Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discriminated unions #16

Closed
BenjaminLindberg opened this issue Aug 27, 2024 · 2 comments
Closed

Discriminated unions #16

BenjaminLindberg opened this issue Aug 27, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@BenjaminLindberg
Copy link
Contributor

Hi, so when I tried to implement discriminated unions for my app i got an error from zod-mongoose, and via the documentation i found out that they're not supported because of a mongoose limitation.
But when checking out the official mongoose docs i found this: https://mongoosejs.com/docs/discriminators.html

So would it be possible to implement discriminated unions, or is that impossible/waste of time?

@bebrasmell
Copy link
Collaborator

bebrasmell commented Aug 29, 2024

Oi!
I've checked that out and there's a conceptional conflict with zod-mongoose.
For top-level discriminators, it should create two (or more) schemas, which is not an expected behaviour in current scope.
Imagine you have a Union field in schema, it accepts two (or more) types, then you'll have two (and more) output schemas. It's alright. But imagine you have two fields with two or more types each, It's already 4 schemas, and for three fields – it's 9 already. To manage those, you would have to build a whole new mongoose wrapper with it's own API.

Simple way to do discriminators is for user to follow the mongoose docs and modify the output schema.
It could work like this:

const zVariant0 = z.object({
  platform: z.enum(["iOS", "Android", "Web"]),
  id: z.string(),
});
const zVariant1 = z.object({
  type: z.enum(["wearable", "beacon"]),
  mac: z.string(),
});

const zUser = z.object({
  name: z.string(),
  device: z.union([zVariant0, zVariant1]),
});

extend(z);

const userSchemaV0 = new Schema("UserSchema", zodSchemaRaw(zUser)); // will consume Union's first type
const userSchemaV1 = userSchemaV0.discriminator(
  "UserSchemaV1",
    zodSchemaRaw(z.object({
      device: zodSchemaRaw(zVariant1),
    });
);

I didn't check it on practice yet, so please consider this answer as just a first thought

@bebrasmell bebrasmell added the enhancement New feature or request label Sep 20, 2024
@bebrasmell
Copy link
Collaborator

Will close this due to lack of activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants
@BenjaminLindberg @bebrasmell and others