Add error to context with nested schemas using Zod validation

I have a Typescript application that is using Zod to validate data. The schema includes several schemas that have slightly different values with nested fields represented by other schemas as they can be reused in other places.

There is a nested object that when any object under a certain level will add an additional error to the Zod context. An example such as this

{
  a: {
    b: { // d or e should both add another error
      d: "1",
      e: "3",
    },
  },
}

So, if d failed validation I want there to be the standard Zod validation error and a custom error added to the context as well. Reading it would seem as though I would want to use superRefine to do this. However, if I add superRefine it does not seem to trigger if the validation failure happens in a nested schema.

Code: https://github.com/rlperez/so-demo-zod

If I had a schema such as this:

const BazSchema = z.string();

const BarSchema = z.object({
  baz: BazSchema
});

const FooSchema = z.object({
  bar: BarSchema
});

When I call FooSchema.parse(obj) that fails for BazSchema does not trigger superRefine if it is written like this:

const FirstSuperRefinedFooSchema = FooSchema.superRefine((data, ctx) => {
  if(!BarSchema.safeParse(data).success) {
    ctx.addIssue({
      code: 'custom',
      message: 'first super refined custom message',
    });
  }
});

and is called like this

  let parseResult = FooSchema.safeParse(wrongTypeBaz);

Output

> [email protected] dev
> npx tsc -t 'es2017' && node ./src/main.js

stupid demo

FirstSuperRefinedFoo
mapping invalid_type
{"error":[{"code":"invalid_type","expected":"object","received":"undefined","path":["bar"],"message":"Required"}]}

The expectation is that it would also have the custom error. I’ve added print statements to make sure it is not reaching superRefine. It’s as if it doesn’t raise the event any further than where it happened. I would need to manually add this to each schema? That seems like a lot of copy and paste across this schema to do that.

How does one do this?