When building robust and reliable applications, data validation is a critical aspect. Zod, a TypeScript-first schema declaration and validation library, offers a powerful way to handle various validation needs, including enums. In this guide, we will explore Zod enum validation in depth, comparing it to native enums, discussing its usage with arrays, and more. We'll also address common scenarios like handling enum error messages and using enums with optional fields.
Zod enum validation allows you to define a set of named values, ensuring that data conforms to one of these predefined options. This is particularly useful when you want to restrict a value to a specific set of possibilities.
To start with Zod enum validation, you define an enum using the
z.enum()
method. This method allows you to specify a list of valid values.
import { z } from 'zod';
// Define a Zod enum
const ColorEnum = z.enum(['Red', 'Green', 'Blue']);
With
ColorEnum
, you can now validate that a value is one of the specified colors.
When comparing Zod enum vs native enum, it's essential to understand that native enums are part of TypeScript's language features, while Zod enums are specifically designed for validation within schemas.
enum Color {
Red = 'Red',
Green = 'Green',
Blue = 'Blue'
}
// Usage
const selectedColor: Color = Color.Red;
const ColorEnum = z.enum(['Red', 'Green', 'Blue']);
const result = ColorEnum.safeParse('Red'); // Valid
Zod enums are more focused on validation and schema enforcement, while native enums provide a way to define and use constant values directly in TypeScript.
To validate a value against a Zod enum, use the
safeParse
method. This method returns an object indicating whether the validation was successful.
const result = ColorEnum.safeParse('Green');
console.log(result); // { success: true, data: 'Green' }
When a value does not match any of the enum options, Zod enum validation will produce an error. You can customize the error message to provide more meaningful feedback.
const CustomErrorEnum = z.enum(['Success', 'Failure']).refine(val => val === 'Success', {
message: 'Only "Success" is allowed.',
});
const invalidResult = CustomErrorEnum.safeParse('Failure');
console.log(invalidResult.error.format()); // Custom error message
Enums can also be used within arrays for more complex validation scenarios. For example, you might have an array of colors where each color must be one of the predefined enum values.
const ColorArrayEnum = z.array(ColorEnum);
const colorsResult = ColorArrayEnum.safeParse(['Red', 'Green']);
console.log(colorsResult); // { success: true, data: ['Red', 'Green'] }
const invalidColorsResult = ColorArrayEnum.safeParse(['Red', 'Yellow']);
console.log(invalidColorsResult.error.format()); // Error due to 'Yellow' not being in the enum
In some cases, you might want to create a Zod enum based on the keys of an object. This can be done dynamically by extracting the keys and using them to define the enum.
const statusObject = {
Pending: 'Pending',
InProgress: 'InProgress',
Completed: 'Completed',
};
const StatusEnumFromObject = z.enum(Object.keys(statusObject) as ['Pending', 'InProgress', 'Completed']);
const statusResult = StatusEnumFromObject.safeParse('Pending');
console.log(statusResult); // { success: true, data: 'Pending' }
Zod enums can also be defined with numeric values. This is useful if your application requires enum values to be numbers rather than strings.
const NumericEnum = z.enum([1, 2, 3] as const);
// Validate numeric enum values
const validNumericResult = NumericEnum.safeParse(2);
console.log(validNumericResult); // { success: true, data: 2 }
const invalidNumericResult = NumericEnum.safeParse(4);
console.log(invalidNumericResult.error.format()); // Error due to '4' not being in the enum
Zod enums can be used with optional fields to allow for scenarios where the value may or may not be present.
const OptionalEnum = z.enum(['Active', 'Inactive']).optional();
// Validate optional enum values
const resultWithValue = OptionalEnum.safeParse('Active');
console.log(resultWithValue); // { success: true, data: 'Active' }
const resultWithoutValue = OptionalEnum.safeParse(undefined);
console.log(resultWithoutValue); // { success: true, data: undefined }
When comparing Zod enum vs union, it’s important to note that while enums are great for defining a fixed set of named values, unions offer flexibility by allowing you to define multiple possible types.
const RoleEnum = z.enum(['Admin', 'User', 'Guest']);
const RoleUnion = z.union([z.literal('Admin'), z.literal('User'), z.literal('Guest')]);
Enums provide a more structured way to handle a specific set of values, while unions can be more flexible but less strict.
To cement your understanding, let’s look at a few more Zod enum examples:
const UserStatusEnum = z.enum(['Active', 'Inactive', 'Suspended']);
const userStatusResult = UserStatusEnum.safeParse('Active');
console.log(userStatusResult); // { success: true, data: 'Active' }
const OrderStatusEnum = z.enum(['Pending', 'Shipped', 'Delivered']);
const orderStatusResult = OrderStatusEnum.safeParse('Shipped');
console.log(orderStatusResult); // { success: true, data: 'Shipped' }
const invalidOrderStatusResult = OrderStatusEnum.safeParse('Cancelled');
console.log(invalidOrderStatusResult.error.format()); // Error due to 'Cancelled' not being in the enum
const MixedEnum = z.union([z.literal('One'), z.literal(2)]);
const mixedEnumResult = MixedEnum.safeParse(2);
console.log(mixedEnumResult); // { success: true, data: 2 }
const invalidMixedEnumResult = MixedEnum.safeParse('Three');
console.log(invalidMixedEnumResult.error.format()); // Error due to 'Three' not being in the enum
Zod enum validation provides a robust and flexible way to handle predefined sets of values in your TypeScript applications. By using Zod enums, you can enforce constraints on data, ensure that values are among a set of valid options, and handle various scenarios such as enums with arrays, object keys, numbers, and optional fields.
Through Zod enum validation, you gain strong type safety and clear validation logic, making your applications more reliable and easier to maintain. Whether you’re comparing Zod enums to native enums, exploring Zod enum vs union, or handling complex validation scenarios, Zod equips you with the tools to handle your data validation needs effectively.
Feel free to experiment with the examples provided and adapt them to fit your specific use cases. By incorporating Zod enums into your projects, you can improve data integrity and enhance the overall quality of your applications. Happy coding!
The official Zod documentation provides comprehensive information on all features, including enums and validation methods.
A detailed guide on TypeScript enums, useful for comparing with Zod enums.
The official GitHub repository for Zod, where you can find additional examples and community discussions.
The primary resource for understanding TypeScript features and best practices.
simplify and inspire technology
©2024, basicutils.com