Published on

Does zod have something equivalent to yup's oneOf() ?

Authors
  • Name
    Ripal & Zalak
    Twitter

Zod Equivalent to Yup's oneOf Method

When using Zod for schema validation, developers often look for an equivalent to Yup's oneOf() method, which allows specifying a list of accepted values for a property. In this post, we'll explore how to achieve the same functionality in Zod efficiently.

The Yup Approach

In Yup, you can easily limit a property to specific values using oneOf:

prop: Yup.string().oneOf(['value1', 'value2', 'value3'])

Achieving the Same in Zod

While Zod does not have a direct oneOf method, it provides multiple ways to implement this functionality.

1. Using z.union with z.literal

You can combine z.literal values using z.union to define a schema with specific accepted values:

import { z } from 'zod'

const schema = z.object({
  prop: z.union([z.literal('value1'), z.literal('value2'), z.literal('value3')]),
})

This approach has the added benefit of inferring the exact type of the property, such as:

prop: 'value1' | 'value2' | 'value3'

2. Creating a Helper Function

To reduce boilerplate, you can write a utility function that simplifies the creation of z.union schemas:

import { z } from 'zod'

function oneOf<T extends string | number | boolean | bigint | null | undefined>(
  values: readonly [T, T, ...T[]]
) {
  return z.union(values.map((value) => z.literal(value)) as [z.ZodLiteral<T>, ...z.ZodLiteral<T>[]])
}

const schema = z.object({
  prop: oneOf(['value1', 'value2', 'value3'] as const),
})

3. Using z.enum

If your accepted values are strings, Zod's z.enum is the most concise and type-safe approach:

const schema = z.object({
  prop: z.enum(['value1', 'value2', 'value3']),
})

This method is both readable and efficient, and it automatically infers the type as:

prop: 'value1' | 'value2' | 'value3'

Comparison of Methods

MethodBest Use CaseExample Values
z.union + z.literalMixed data types (e.g., strings, numbers)[5, 10, 15]
Helper FunctionReusable logic for multiple schemas["A", "B", "C"]
z.enumString-only values["yes", "no"]

FAQs

Can Zod handle dynamic values for validation?

Zod works best with statically defined schemas. For dynamic validations, you can use z.custom or superRefine for more complex logic.

Which method is most type-safe?

Using z.enum or z.union with z.literal ensures strict type safety in TypeScript.

Can I validate against a large list of values?

For a large list of allowed values, consider using a helper function or z.custom with dynamic logic to improve maintainability.