Typing API Responses With Zod

Have you ever needed to synchronize types in your frontend app with the backend API?

If you ever had an API action defined like that in your controller:

public record UserViewModel(Guid Id, string Name, string LastName, string Login,
bool IsActive, int LoyaltyPoints, AddressViewModel? Address = null);
// …
public List<UserViewModel> AllUsers()
{
var usersViewModels = TestDataGenerator.GetTestUsers();
return usersViewModels.OrderBy(uvm => uvm.Name).ToList();
}

and fetched this data using TypeScript in the following way:

getAllUsers = async (): Promise<UserViewModel[]> => {
const url = `${this.apiEndpoint}/AllUsers`;
const response = await fetch(url);
const users = (await response.json()) as UserViewModel[];
return users;
};

at some point, you probably also experienced the desynchronization of backend (C#, in our example) and frontend (TypeScript) types definitions. What if someone has changed the C# version of UserViewModel, but no one corrected its TypeScript’s equivalent?

Your TypeScript fetching code will tell nothing about that. There will be no error, even though the fetched data doesn’t match the expected UserViewModel type.

I’ll try to address this issue in this article 🙂 Let’s see how typing API responses with zod can help us here.