Does zod have something equivalent to yup's oneOf()
Asked Answered
N

2

8

If I had a property that should be limited to only a few possible values, using Yup I could do something like:

prop: Yup.string().oneOf([5, 10, 15])

I can not seem to find something similar in Zod. Of course, I can do that validation in the following way:

const allowedValues = [5, 10, 15];

const schema = z.object({
  prop: z.number().superRefine((val, ctx) => {
    if (allowedValues.includes(val)) return true;

    ctx.addIssue({
      message: `${ctx.path} must be one of ${allowedValues}`,
      code: "custom",
    });
    return false;
  }),
});

But I was wondering if it could be done by writing less code.

Nigeria answered 26/12, 2022 at 14:56 Comment(0)
K
9

In this particular case you could use z.union with z.literal to at least write the code more declaratively:

const schema = z.object({
  prop: z.union([z.literal(5), z.literal(10), z.literal(15)]),
});

This approach also has the added benefit of parsing the exact type 5 | 10 | 15 as the result rather than simply number.

That can get slightly tedious to write out so it might make sense if you find yourself doing this a lot to write a quick helper like:

// This signature might be a bit overkill but these are the types
// z.literal allows.
function oneOf<T extends string | number | boolean | bigint | null | undefined>(
  t: readonly [T, T, ...T[]],
) {
  // A union must have at least 2 elements so to work with the types it
  // must be instantiated in this way.
  return z.union([
    z.literal(t[0]),
    z.literal(t[1]),
    // No pointfree here because `z.literal` takes an optional second parameter
    ...t.slice(2).map(v => z.literal(v)),
  ])
}

// This will be equivalent to the first schema
const schema2 = z.object({
  // This will still typecheck without as const but with weaker
  // types than the first example.
  prop: oneOf([5,10,15] as const),
});
Kennykeno answered 26/12, 2022 at 15:36 Comment(0)
A
0

If the type you're dealing with is set of string literals, there's a shorthand operator you can use in newer versions of Zod:

type Levels = "One" | "Two" | "Three"

const LevelsSchema = z.enum(["One", "Two", "Three"])

Adventitia answered 14/9, 2024 at 3:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.