Modern React Data-Fetching with TypeScript, React-Query, and Zod
Luckily, there's a relatively straight-forward solution to the problem of interacting with untyped APIs in TypeScript-based React.
The Building Blocks
The first piece of this puzzle is the incredible React Query. If you're not currently using React Query in your project you should immediately take a step back and ask yourself why. Data fetching has long been a contentious topic in React, and since the arrival of hooks, a lot of developers (myself included) have made the mistake of misusing
useEffect or rolling our own data-fetching libraries. Much like rolling your own authentication system, this can bite you.
The second piece is Zod. While there are a lot of validation libraries out there, Zod is the current frontrunner and you should be using it unless you absolutely, positively have a reason to use something else. Zod's validation and ability to easily infer TypeScript types is going to be key to typing our untyped API.
Putting It Together
The solution is surprisingly concise: Write a Zod validator for the API endpoint, use it to parse the response from the API, and get a typed result in React Query. Let's look at an example of this with a user information API endpoint:
That's it! The resulting
query.data will be typed as either the schema or
undefined (since queries can fail). If the response from the API fails validation, you'll get an error which you can deal with in development or even catch in production with whatever exception logging tool you're using.
While this solution isn't as automatic as tRPC and requires you to write a bit of boilerplate, it does scale well and makes dealing with untyped API endpoints less painful in TypeScript.