'Zod - Setting length limits to combined arrays in an object

I'm using Zod for developing these schemas. I have an object with two fields, each of them an array. I want to place a limit so that the combined length of those two arrays doesn't exceed three. Any idea on how to approach that? Code below.

export const personality = z.object({
   enumInput: personalityEnum.array(),
   customInput: z.string().length(20).array()
})

export type Personality = z.infer<typeof personality>


Solution 1:[1]

A bit of a late answer here, but I think you can accomplish this using refine:

import { z } from "zod";
enum PersonalityType {
  Grumpy = "grumpy",
  Sleepy = "sleepy",
  Bashful = "bashful"
}
const personalityEnum = z.enum([
  PersonalityType.Grumpy,
  PersonalityType.Sleepy,
  PersonalityType.Bashful
]);
export const personality = z
  .object({
    enumInput: personalityEnum.array(),
    customInput: z.string().length(20).array()
  })
  .refine(
    (input) => {
      return input.customInput.length + input.enumInput.length <= 3;
    },
    {
      message:
        "The combined length of enumInput and customInput may not be longer than 3"
    }
  );

export type Personality = z.infer<typeof personality>;

const test1 = personality.safeParse({
  enumInput: [
    PersonalityType.Sleepy,
    PersonalityType.Grumpy,
    PersonalityType.Bashful
  ],
  customInput: ["Sneezy but length 20"]
});
// This fails with the custom error message
const test2 = personality.safeParse({
  enumInput: [PersonalityType.Sleepy],
  customInput: ["Sneezy but length 20"]
});
// This succeeds!

Aside

I noticed while working on this that the .length(20) refinement means that the custom inputs must be exactly 20 characters long. Is this what you intended? If you were looking for a string to be at most 20 characters I think max(20) is what you want.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Souperman