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

The result of zod.preprocess v3.22.2 is ignored and falls back to the original value inside a further refine #2671

Open
azhiv opened this issue Aug 21, 2023 · 2 comments
Labels
bug-confirmed Bug report that is confirmed

Comments

@azhiv
Copy link
Contributor

azhiv commented Aug 21, 2023

This code is on sandbox. We noticed this behaviour in v3.22.2.

const schema = zod
  .object({
    inactiveObject: zod
      .object({
        isInactive: zod.boolean(),
      })
      .refine(
        ({ isInactive }) => isInactive === false, // <-- This refine fails leading to the preprocess below to be ignored
        { message: 'object is inactive' }
      ),
    arr: zod.preprocess((val) => [val], zod.array(zod.object({}))), // <-- The result of this code is ignored, `arr` remains `val` in the refine below
  })
  .refine(({ arr }) => arr.some((elem) => elem !== null)); // arr.some is not a function

schema.safeParse({
  inactiveObject: {
    isInactive: true,
  },
  arr: {},
});

I debugged the code and it turns out the bug occurs here:

if (effect.type === "preprocess") {
  const processed = effect.transform(ctx.data, checkCtx);
  if (ctx.common.issues.length) {
      return {
          status: "dirty",
          value: ctx.data
      };
  }
...

-- the result of transform is ignored. This condition was absent in v.3.21.4 which worked fine for the usecase above.

@azhiv azhiv changed the title The result of zod.preprocess v3.22.4 is ignored and falls back to the original value The result of zod.preprocess v3.22.4 is ignored and falls back to the original value inside a further refine Aug 21, 2023
@azhiv azhiv changed the title The result of zod.preprocess v3.22.4 is ignored and falls back to the original value inside a further refine The result of zod.preprocess v3.22.2 is ignored and falls back to the original value inside a further refine Aug 21, 2023
@JacobWeisenburger
Copy link
Contributor

Perhaps using transform and pipe will work for you instead?

const schema = z.object( {
    inactiveObject: z.object( { isInactive: z.boolean() } ).refine(
        ( { isInactive } ) => isInactive === false,
        'object is inactive'
    ),
    arr: z.any().transform( x => [ x ] ).pipe( z.object( {} ).array() ),
} ).refine( ( { arr } ) => arr.some( x => x !== null ) )

const result = schema.safeParse( {
    inactiveObject: {
        isInactive: true,
    },
    arr: {},
} )
!result.success && console.log( result.error.issues )
// [
//     {
//         code: "custom",
//         message: "object is inactive",
//         path: [ "inactiveObject" ]
//     }
// ]

If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏
https://github.com/sponsors/JacobWeisenburger

@andreyfel
Copy link

The issue seems to be fixed with v3.23.0 by #2912

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug-confirmed Bug report that is confirmed
Projects
None yet
Development

No branches or pull requests

3 participants