Skip to Content

Last Updated: 3/12/2026


Literals

Literal schemas represent a literal type , like "hello world" or 5.

Basic Literals

import * as z from "zod"; const tuna = z.literal("tuna"); const twelve = z.literal(12); const twobig = z.literal(2n); // BigInt literal const tru = z.literal(true); tuna.parse("tuna"); // ✅ "tuna" tuna.parse("salmon"); // ❌ throws

Special Literals

To represent the JavaScript literals null and undefined:

z.null(); z.undefined(); z.void(); // equivalent to z.undefined()

Multiple Literal Values

To allow multiple literal values, you can pass an array:

const colors = z.literal(["red", "green", "blue"]); colors.parse("green"); // ✅ colors.parse("yellow"); // ❌ throws

Extracting Values

To extract the set of allowed values from a literal schema:

colors.values; // => Set<"red" | "green" | "blue">

Literals vs Enums

While literals and enums might seem similar, they serve different purposes:

Literals

  • Represent a single specific value
  • Useful for exact value matching
  • Often used in discriminated unions
const status = z.literal("success"); // Only accepts exactly "success"

Enums

  • Represent a set of possible values
  • Provide utility methods (.enum, .exclude(), .extract())
  • Better for multiple options
const status = z.enum(["success", "error", "pending"]); // Accepts any of the three values

Common Use Cases

Discriminated Unions

Literals are commonly used as discriminators in union types:

const Result = z.discriminatedUnion("status", [ z.object({ status: z.literal("success"), data: z.string() }), z.object({ status: z.literal("error"), error: z.string() }), ]);

Boolean Flags

const enabled = z.literal(true); const disabled = z.literal(false);

Magic Numbers

const HTTP_OK = z.literal(200); const HTTP_NOT_FOUND = z.literal(404);

Versioning

const ApiV1 = z.object({ version: z.literal(1), // ... v1 fields }); const ApiV2 = z.object({ version: z.literal(2), // ... v2 fields }); const ApiRequest = z.union([ApiV1, ApiV2]);

Type Inference

const schema = z.literal("hello"); type Schema = z.infer<typeof schema>; // "hello" (not string) const numSchema = z.literal(42); type NumSchema = z.infer<typeof numSchema>; // 42 (not number)

Best Practices

  1. Use literals for discriminators in discriminated unions
  2. Use enums for multiple options instead of unions of literals
  3. Prefer literals over magic values for better type safety
  4. Combine with unions to create flexible yet type-safe schemas