As the world becomes increasingly digitized, APIs (Application Programming Interfaces) have become a crucial component of software development. They provide a standardized way for different applications to communicate with each other, making it easier to integrate different systems and services. One of the challenges of working with APIs is ensuring that the data being sent and received is properly structured and validated. In this article, we will walk through the steps of using four powerful tools to achieve this: getting a JSON test response from an API, using quicktype to convert JSON to Typescript type, using Zod to write a schema following the structure of the generated type, and using ts-toolbelt to ensure that the Zod schema is the same or extends the generated type.
Step 1: Get JSON Test Response from an API
Before we can begin working with APIs, we need to obtain a test response that we can work with. In this example, we will be using the JSONPlaceholder API to get a test response. We will make a GET request to the /todos endpoint to get a list of to-dos
. The response will be in JSON format and will look something like this:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
...
]
We will save this response in a file called test-response.json
.
Step 2: Use Quicktype to Convert JSON to Typescript Type
Now that we have a test response, we can use quicktype to generate a Typescript type based on the JSON structure. Quicktype is a powerful tool that can generate types for a variety of programming languages and data formats, including JSON, XML, and CSV. It uses machine learning algorithms to analyze the structure of the data and generate a type that matches it.
To use quicktype, we can simply run the following command:
npx quicktype test-response.json -o todo.ts --just-types
Note: Quicktype has a VScode extension to paste JSON and convert to type
This will generate a file called todo.ts
that contains a Typescript type that matches the structure of the JSON response. The contents of the file will look something like this:
export interface Todo {
userId: number;
id: number;
title: string;
completed: boolean;
}
This generated Typescript type serves as documentation for the structure of the JSON response but this is only helps us when we code. We can do better. We can validate at run time.
Step 3: Use Zod to Write a Schema Following the Structure of the Generated Type
Now that we have a Typescript type that matches the structure of the JSON response, we can use Zod to write a schema that enforces the structure of the type. Zod is a powerful schema validation library that can be used to validate data against a schema in Typescript.
To use Zod, we first need to install it:
npm install zod
Next, we can write a schema that matches the structure of the Todo type that we generated in the previous step:
import * as z from 'zod';
const todoSchema = z.object({
userId: z.number(),
id: z.number(),
title: z.string(),
completed: z.boolean()
});
This schema enforces that the userId
and id
properties are numbers, the title property is a string, and the
completed
property is a boolean, just like in the original JSON response. We can now use this schema to validate any data that we receive from the API to ensure that it matches the expected structure.
Step 4: Use ts-toolbelt to Ensure that the Zod Schema is Same or Extends the Generated Type
While we have written a schema that matches the structure of the generated Typescript type, there is still a chance that the schema could become out of sync with the type as our codebase evolves. To prevent this from happening, we can use ts-toolbelt to ensure that the schema is the same or extends the generated type.
To use ts-toolbelt, we first need to install it:
npm install ts-toolbelt
Next, we can write a type that takes a schema and a Typescript type and uses ts-toolbelt to ensure that the schema is the same or extends the type. We do that by writing below in a file that you do not execute. It only serves to highlight errors in VSCode.
import { A, Test } from "ts-toolbelt";
import { todoSchema } from "./schema"
const { checks, check } = Test;
type validation = A.Equals<z.infer<typeof todoSchema>, Todo>;
checks([check<validation, 1, Test.Pass>()]);
Now since Zod only validates at runtime it can't tell you in VSCode that the schema is wrong but when you compare the generated type with it and there's a mismatch VSCode will tell you about it. Also as example if you run it in a CI pipeline against a testing API you will know if the API has changed so you can update your code before they update their production API.
Conclusion
In this article, we have walked through the steps of using four powerful tools to ensure that the data we receive from an API is properly structured and validated. We started by getting a JSON test response from an API, then used quicktype to generate a Typescript type based on the response. We then used Zod to write a schema that matched the generated type, and finally used ts-toolbelt to ensure that the schema was the same or extended the type. By following these steps, we can ensure that our API integration is robust, reliable, and easy to maintain over time.
Top comments (0)