Work with Zod Literals and Enums Effectively

In this lesson we make string-based schemas more specific using Zod in TypeScript. We focus on defining allowed values for a room type, showing how to use literals and enums effectively.

Zod's z.literal method allows us to specify a single allowed value for a string schema. For example, if we want to define a room type as "premium" and make it backward-type-safe in TypeScript, we can use z.literal("premium") to ensure that only this value is valid.

z.enum lets us define a set of allowed string values. This is useful when we have multiple options for room types, like "standard", "premium" or "childrenFriendly".

z.enum creates a union of TypeScript-compatible string literals, making it easy to validate against multiple values. Zod enums can be used to extract or exclude specific values from the enum.

Finally, zod's z.nativeEnum a native enum creates an equivalent of TypeScript's native enum ("real enums", we could say).

We can validate against all these values just like we do with literals and enums.

Share with a coworker

Transcript

[00:00] Sometimes we want to make our string-based schema more specific, but not by running a custom function invocation in runtime, but just by providing what are the allowed values within a string schema. So here we've got a room type which has a premium value and we will see the literals, enums and native enums in action. So let's first run this file against ts-node to see that here everything is valid since The value is premium and currently our room type is just a string schema. So first one is going to be a literal. So this is Z.literal and here since our value is a premium, then we're just going to put the premium over here and let's see what is going to be the inferred TypeScript type.

[00:51] So this is going to be z.infer of type of whatever the schema is. And here what we can see that it's not just any string, but it's the premium value. So let's also put this standard room literal over here. So this is going to be this one. Let's save the file.

[01:11] Let's run the validation and we will see that everything is valid over here. So z.literal is being used when we have a single literal. So this is important. It's not for providing a whole set of literal, but just a single one. So let's now use a whole set of literal values.

[01:31] And this is called z.enum. So this could be slightly confusing. This is not a native enum. This is just going to be a whole set, a whole pack of such z.literals. So in our case, let's say that this would be a standard room type or the premium one or let's say also that could be a children friendly whatever.

[01:53] And we can also see that the T2 type is going to be a String literal union in TypeScript. Not a native enum, but just string literal union. So let's also use this room type enum over here within our room schema. Let's run this file. Booking is valid.

[02:15] Now let's see how could an extracted subset of the enum work. So what we can do is basically to get this schema, to grab it, and to extract only some parts that we want right here, right now. And let's say that we want to extract only ones that we pass over here. So let's say that we only want to pass the premium and we will see that T3 is again out of the three. We extracted only the one.

[02:43] So it behaves the same way as TypeScripts extract conditional built in utility type. Let's also pass it over here to see that our validation works correctly. Let's also see how the exclusion works. So we're going to exclude a subset from the enum. So let's again grab the room type enum, which is our reference point, and let's run exclude and we're going to exclude only the children friendly.

[03:15] So whatever we should be left with is the standard and the premium values. So let's also see what gets inferred. So in this case is the premium and standard all as expected. Let's also run the validation of the file and we will see that everything is cool, booking is valid and finally let's see the real enum, so something that is going to behave as an enum in TypeScript. So this one is going to be z.nativeenum.

[03:50] So let's create enum room type with standard, premium and children friendly. And in order to provide the native enum, we pass the real TypeScript enum. So finally, z.infer and here we can pass whatever is the type of the native enum. And we would see that, yes, this is the enum itself. So we can see that Zot hasn't modified anything over here.

[04:22] And we can also validate against these values over here. So let's take the native room type enum and let's put it over here. And let's finally run the validation to see that the booking is valid. So again, remember that ZLiteral is for a single literal and for multiple literal values is the ZEnum, which is not the same as the native enum itself.