⛓️ Enforcing the shape of an API response with zod

Sometimes you might want to ensure that the returned response from an API conforms to a given shape. For this you can use the zod library. This library allows you to define and enforce a schema for the APIs that you’ll be calling in your application.

Let’s see how it works with an example. Imagine you have a weather API that returns the following JSON object:

{
  "city": "Madrid",
  "temperature": 25,
  "units": "celsius"
}

You know that the API returns an object with 3 keys: city, temperature and units. You also know that the value for the city key is a string, for the temperature one is a number and for the units one a set of pre-defined strings (e.g. fahrenheit and celsius). Then, you could define the following schema:

import { z } from 'zod';

const WeatherSchema = z.object({
  city: z.string(),
  temperature: z.number(),
  units: z.enum(['fahrenheit', 'celsius'])
});

Now, you can use this schema to parse the response from the API:

const response = await getWeather("Madrid");

const parsedResponse = WeatherSchema.parse(response);

If the response conforms to the schema the code will continue its execution and parsedResponse will have the same values that are present in the response object. On the other hand, if the API returned something else (e.g. “kelvin” in the units, or an additional field in the object) zod would throw an exception that you would be able to catch and act accordingly.

Finally, another positive aspect of using zod is that the parsedResponse variable will be typed, so intellisense (code completion, parameter info, etc) will be available in your code editor.

If you want to extract the type from a schema so you can use it throughout your code you can do the following:

type Weather = z.infer<typeof WeatherSchema>;