In Zod, z.enum
allows you to restrict inputs to a predefined set of string values, making it ideal for validating user roles, statuses, or form options—think of it like a dropdown menu where users must pick a valid option.
Beyond basic usage, this guide covers powerful features like:
- Generating enums from object keys using
z.enum(Object.keys())
- Creating enums from TypeScript using
z.nativeEnum
- Supporting case-insensitive enum validation
- Customizing error messages for better UX
Whether you’re working with plain strings or real TypeScript enums, Zod makes enum validation both strict and flexible.
Defining and Parsing Enum in Zod
const StatusSchema = z.enum(["draft", "published", "archived"]);
StatusSchema.parse("draft"); // Valid
StatusSchema.parse("Draft"); // Error: not one of the allowed values
StatusSchema.parse("deleted"); // Error: not one of the allowed values
The enum is case-sensitive and does not allow any value outside the provided list. This ensures that only "draft"
, "published"
, or "archived"
are accepted—making your data clean, predictable, and safe.
But that’s not the only way to define enums in Zod.
Zod offers multiple ways to create and validate enums depending on your data structure or development style. You can:
- Create enums from an array of strings
- Generate enums from object keys or object values
- Use existing TypeScript enums
- Define enums from TypeScript union types
Generating Enums from Object Keys in Zod
In some cases, you may want to create a Zod enum schema from the keys of an existing object—especially when those keys represent constants like permissions, flags, or modes.
const permissions = {
READ: true,
WRITE: false,
DELETE: true,
};
const PermissionSchema = z.enum(Object.keys(permissions) as [keyof typeof permissions, ...string[]]);
In this example:
permissions
is a plain object whose keys represent allowed values.Object.keys(permissions)
returns an array of strings:["READ", "WRITE", "DELETE"]
.- Zod requires a tuple (not just a string array), so we cast it as
[keyof typeof permissions, ...string[]]
to ensure type safety.
Handling Case Insensitive Enum Validation in Zod
Working with enums often requires strict value matching. But in real-world applications, users or APIs might send values in different cases — "active"
, "ACTIVE"
, or "Active"
. Zod enums (z.enum()
or z.nativeEnum()
) are case-sensitive by default, so how do we make enum validation case-insensitive?
To ignore case while parsing enums, use z.preprocess()
to normalize the input string before validation:
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE",
}
const CaseInsensitiveStatus = z.preprocess(
(val) => typeof val === "string" ? val.toUpperCase() : val,
z.nativeEnum(Status)
);
// All of these pass:
CaseInsensitiveStatus.parse("active");
CaseInsensitiveStatus.parse("ACTIVE");
CaseInsensitiveStatus.parse("Active");
Enum Error Handling in Zod
Zod provides powerful tools to handle errors gracefully when working with enums. While the default error messages are helpful, customizing them ensures a better developer and user experience. Whether you’re validating user roles, statuses, or fixed options, you can fine-tune error handling to match your application’s tone and clarity needs.
There are two main ways to handle error messaging in Zod enum validation:
- Generic Error Messages – Apply a single, static message for all invalid values. Ideal for simple use cases where one friendly message is enough.
- Varying Custom Messages Using
errorMap
– Define dynamic, context-aware messages based on the input or error type. This is perfect for delivering precise feedback tailored to each validation failure.
Custom Error Messages for Zod Enums
When working with zod.enum
or z.nativeEnum
, developers often encounter invalid enum value errors. By default, Zod throws a generic error message like:
“Invalid enum value. Expected one of …”
But for a better developer or end-user experience, it’s smart to replace this with a custom error message that’s more clear and helpful. Zod allows full customization using errorMap
or .refine()
to define Zod enum custom error messages.
const ColorSchema = z.enum(["RED", "GREEN", "BLUE"], {
errorMap: () => ({
message: "Please select a valid color: RED, GREEN, or BLUE."
})
});
ColorSchema.parse("RED"); // ✅ OK
ColorSchema.parse("yellow"); // Throws: Please select a valid color: RED, GREEN, or BLUE.
Customizing error messages with z.nativeEnum
is just as simple. This is useful when you’re validating against backend-provided enums or shared constants in TypeScript.
enum Mode {
Auto = "AUTO",
Manual = "MANUAL"
}
const ModeSchema = z.nativeEnum(Mode, {
errorMap: () => ({
message: "Mode must be either AUTO or MANUAL."
})
});
ModeSchema.parse("AUTO"); // ✅ OK
ModeSchema.parse("eco"); // ❌ Error: Mode must be either AUTO or MANUAL.
Enum Utility Methods in Zod
Zod provides two helpful utility methods to refine enums: exclude()
and extract()
. These methods allow you to create subsets of an existing enum schema without redefining it manually.
exclude()
removes one or more values from the original enum. It’s useful when you want to filter out certain options, such as disallowing “guest” in restricted user roles.extract()
lets you pick specific values from the enum. This is ideal when you only want to allow certain roles, statuses, or categories in a specific context.
These methods are especially valuable in real-world scenarios like:
- Restricting access to admin-only features by excluding public roles
- Creating a validation schema that allows only publishable content states
- Dynamically tailoring enum schemas based on form flows or API routes
By using exclude()
and extract()
, you keep your code DRY, improve maintainability, and ensure consistent validation across your app.
Conclusion
Zod’s z.enum
gives you precise control over string-based validation by enforcing a strict set of allowed values. Whether you’re validating content statuses like "draft"
and "published"
, user roles such as "admin"
and "viewer"
, or any other fixed choices, z.enum
ensures only those exact values pass.
You can create enums from string arrays, object structures, or TypeScript types, and easily refine them with utility methods like extract()
and exclude()
—perfect for tailoring validations in different parts of your app.
Combined with custom error messages using errorMap
, Zod enums let you deliver accurate, user-friendly validation while keeping your schemas consistent and maintainable across your codebase.
While this guide gives you real-world patterns and use cases beyond the basics, you can also refer to the official Zod documentation on enums for the raw API reference.