zod icon indicating copy to clipboard operation
zod copied to clipboard

Question: How to extend/copy array schema but only change the containing type

Open brupxxxlgroup opened this issue 1 year ago • 2 comments

Hello

I have a question regarding arrays.

Given following simple example

const myObjSchema = z.object({
  name: z.string(),
});

const arrayOfMyObj = z.array(myObjSchema).min(1).max(2);

What i wanna do is kind of changing the containing type of the array like this.

const arrayOfMyObjExt = arrayOfMyObj.changeType(myObjSchema.extend({ foo:z.string()}));

but i want to keep the constraints of min and max of the original array.

Why do i need this?

I want to extend and existing schema with some OpenAPI documentation and i do not have access to the original schema definitions. I want to keep as much from the original schema as possible to not run out of sync. For z.object i can use extends but there is nothing like this for z.array.

Any hints?

Thank you so much for help.

brupxxxlgroup avatar Aug 26 '24 14:08 brupxxxlgroup

Maybe you can try something like this:

const arrayOfMyObj = z.array(myObjSchema).min(1).max(2);

const newSchema = arrayOfMyObj.and(
  z.array(
    z.object({
      foo: z.string(),
    })
  )
);

Transforms original schema into an Intersection type.

sunnylost avatar Aug 28 '24 13:08 sunnylost

Hi, @brupxxxlgroup. I'm Dosu, and I'm helping the Zod team manage their backlog. I'm marking this issue as stale.

Issue Summary:

  • You were looking to modify the type of elements within a Zod array schema while keeping constraints like min and max.
  • The goal was to extend an existing schema with additional properties for OpenAPI documentation without access to the original schema definitions.
  • @sunnylost suggested using an intersection type with the and method, providing a code example that seems to resolve your requirement.

Next Steps:

  • Please confirm if this issue is still relevant to the latest version of the Zod repository. If so, you can keep the discussion open by commenting here.
  • Otherwise, this issue will be automatically closed in 7 days.

Thank you for your understanding and contribution!

dosubot[bot] avatar Jun 17 '25 16:06 dosubot[bot]

I'm a bot trained on Zod's codebase and issues.

There's no built-in .changeType or similar method in Zod v3 to swap the item type of an array schema while keeping constraints like .min() and .max(). However, you can programmatically create a new array schema by copying the constraints from the original schema. Constraints like minLength and maxLength are stored on the internal _def property of the array schema instance (see code).

Here's a utility function for Zod v3:

function copyArraySchemaWithNewType(originalArraySchema, newItemSchema) {
  const def = originalArraySchema._def;
  const newDef = { ...def, type: newItemSchema };
  // @ts-ignore: Accessing internal constructor
  return new originalArraySchema.constructor(newDef);
}

// Usage:
const arrayOfMyObjExt = copyArraySchemaWithNewType(
  arrayOfMyObj,
  myObjSchema.extend({ foo: z.string() })
);

This approach uses internal APIs, so it's not officially supported and may break with future updates.

If you're using Zod v4, there's a public .clone() method on all schemas. You can do:

const arrayOfMyObjExt = arrayOfMyObj.clone({ element: myObjSchema.extend({ foo: z.string() }) });

This is the recommended and stable way in Zod v4.

Let me know if this solves your problem or if you need a more detailed example. If your question is answered, please close the issue!

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Join Discord Share on X

dosubot[bot] avatar Jul 21 '25 22:07 dosubot[bot]