Zod Tutorial (10 exercises)
solution

Update the toString Function

Create a numberParser

Parsers are one of the most basic features of Zod.

To start our solution, we'll create a numberParser by invoking z.number().

This creates something called z.ZodNumber that provides several helpful methods.

const numberParser = z.number();

Passing data into numberParser.parse() will error if it's not a number.

This means that any variable we create by calling numberParser.parse() will be typed as a number, and our tests pass!

Here's our updated toString function after adding in numberParser:

const numberParser = z.number();

export const toString = (num: unknown) => {
  const parsed = numberParser.parse(num);
  return String(parsed);
};

Experiment with Different Types

Zod allows us to use this same technique with other types as well.

For example, if we wanted to accept a boolean instead, then we could update our numberParser to be z.boolean().

Now our tests will fail because they expected a number but got a Boolean.

This technique with Zod gives us a solid base to build up from. As we proceed, you'll find that Zod mimics a lot of what you're used to in TypeScript.

Check out the full list of primitives in the Zod docs.

Transcript

The solution here is to use the very, very basic stuff that Zod gives you, which is, first of all, we're going to create a numberParser. This numberParser is going to be invoked from z.number. This creates something called z.ZodNumber.

We can use numberParser in a bunch of ways. We can go .parse. We can pass in some random data. It will error if it's not a number. Anything that we return from this, as you can see, numberParser.parse(num), this is now typed as a number. If we wanted to accept a Boolean instead, then we would go z.boolean. Now this would be typed as a Boolean.

Importantly, it's now erroring correctly. It's expecting a number but received a string, when this is called. Here, if we instead change it to be a Boolean, then this will error, but it's going to error in the wrong way, "Expected boolean, received number." Rather, that's on the one down there.

These really basic elements of Zod here, like z.string, z.boolean, z.number, these are really, really important primitives because they allow you to build up from a solid base.

They represent the basic elements of TypeScript too. You've got Boolean. You've got string. You've got number. You've got bigint and null and undefined. You can even have z.undefined, z.null. What you'll start to see about Zod is that it mimics a lot of what you're used to in TypeScript with its runtime type system.