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

Property in response body is marked as nullable even when nulls for it are being filtered out via preprocess/transform #263

Open
roun-dfs opened this issue Oct 4, 2024 · 0 comments

Comments

@roun-dfs
Copy link

roun-dfs commented Oct 4, 2024

Hello

First of all, thank you for this great library. It's nice to be able to use zod in more places.

I'd like to ask about a potential bug and propose a potential fix for it which might not be perfect but it should definitely resolve my issue and maybe help others as well.

My use case is that I have to proxy some responses from another server and some properties from those responses could be missing, undefined or null so I've tried using preprocess and/or transform from zod to replace those nulls with undefined, or a default value where appropriate, and everything works great except for the fact that those properties end up being marked with nullable: true in the response dto even though nulls are being filtered so they won't ever be returned. Here's an example response schema:

const proxiedResponseSchema = z.object({
  someId: z.string().uuid(),
  someName: z.string(),
  someFlag: z.preprocess((value) => value ?? false, z.boolean()),
  someList: z.array(z.string()).nullish().transform((value) => !value || value.length === 0 ? ['default'] : value),
});

In the example from above, both someFlag and someList are currently marked with nullable: true because their schemas accept null which would be perfectly fine it this was the schema for a request body but it is the schema for a response body so the output of the schema should matter instead of the input.

Is this a bug or this intended behaviour and I'm misunderstanding something?

From my short investigation I found out that this happens because ZodType.prototype.isNullable is always called directly without taking into account whether the schema is for input (e.g. request body) or output (e.g. response body) when that method simply tells if a schema accepts null and it doesn't tell if null will also be returned. I haven't figured out yet if input dtos and output dtos are being handled differently by this lib but if they are then I'd like to recommend the following solutions:

  1. for z.preprocess, a version of this method which already handles isOptional, should definitely work for isNullable as well
  2. for .transform, maybe extend the check that zod already does for isNullable so it checks that null can be not only accepted by the schema but also returned by it, in other words zodSchema.safeParse(null).data === null?

Would be perfect to have both solutions so preprocess and transform can both be used in response dtos but I understand that the proposed solution for transform might not be perfect.

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

No branches or pull requests

1 participant