Published on

Validating Exact Values with Zod

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Validate Exact Values with Zod ?

When working with Zod, a popular schema validation library, you might encounter scenarios where you need to validate exact values rather than ranges or patterns. Thankfully, Zod provides a simple and elegant solution: literals.

In this blog, we’ll explore how to use Zod literals to validate exact values for various data types like numbers, strings, and more.


Problem Statement

Validating values like a specific number or string in a schema can be tricky. While regex works for strings, and bounds (gte, lte) work for numbers, these approaches can feel cumbersome when you want to validate against an exact value.

Example of a workaround for numbers:

const myNumber = z.number().gte(7).lte(7) // Works but is not idiomatic

For a cleaner solution, Zod offers literals.


The Zod Literal Solution

Zod literals allow you to validate a schema for a specific exact value. The inferred TypeScript type will also be narrowed to that exact value.

Syntax

const schema = z.literal(value)

Example Use Cases

1. Validate an Exact Number

const exactNumber = z.literal(7)

type ExactNumberType = z.infer<typeof exactNumber> // Type: 7

const result = exactNumber.safeParse(7) // Valid
console.log(result.success) // true

const invalidResult = exactNumber.safeParse(5) // Invalid
console.log(invalidResult.error.issues) // Shows error details

2. Validate an Exact String

const exactString = z.literal('Hello, World!')

type ExactStringType = z.infer<typeof exactString> // Type: "Hello, World!"

const valid = exactString.safeParse('Hello, World!') // Valid
console.log(valid.success) // true

const invalid = exactString.safeParse('Hello') // Invalid
console.log(invalid.error.issues) // Shows error details

3. Combine with Union for Multiple Exact Values

You can use Zod literals with unions to allow multiple specific values:

const allowedValues = z.union([z.literal('red'), z.literal('green'), z.literal('blue')])

type AllowedValuesType = z.infer<typeof allowedValues> // Type: "red" | "green" | "blue"

const validColor = allowedValues.safeParse('green') // Valid
console.log(validColor.success) // true

const invalidColor = allowedValues.safeParse('yellow') // Invalid
console.log(invalidColor.error.issues) // Shows error details

4. Literal for Booleans

const exactBoolean = z.literal(true)

const validBool = exactBoolean.safeParse(true) // Valid
console.log(validBool.success) // true

const invalidBool = exactBoolean.safeParse(false) // Invalid
console.log(invalidBool.error.issues) // Shows error details

FAQs

1. What types can I use with z.literal?

You can use z.literal with:

  • Primitive types: string, number, boolean
  • null
  • Other constants like undefined

2. Can I validate against multiple literals?

Yes, you can use z.union to combine multiple literals, allowing any of the specified exact values.

3. How is this useful in APIs?

Validating exact values ensures consistency. For example, when accepting fixed options in an API request, you can validate against specific strings or numbers.