Building a Typesafe API Wrapper
A Clean Solution to a Tedious TypeScript Problem
“Type Safety: Where code wears a seatbelt even before hitting the road.”
Today I present to you a lightweight, framework-agnostic API wrapper to guarantee Typesafe data fetching
Requires minimal boilerplate, and it builds upon the standard fetch
API, therefore no additional dependencies to bloat your applications.
So without further ado… Lets dive right in.
Creating our Type Definition
Lets begin by creating a simple type, CreateAPIMethod
, that will specify the expected inputs and outputs for our API, plus all necessary options to make the API call (e.g. request method, URL).
// The Generic API method should always specify the expected input "T"
// and output "U" The "opts" include the API url and the request method.
// You could extend this to accept more options.
// This returns a function that takes in the expected input "T"
// and returns a Promise for "U" which emulates the functionality
// of a simple fetch request.
export type CreateAPIMethod = <
T extends Record<string, string> | undefined,
U
>(opts: {
url: string
method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE"
}) => (input?: T) => Promise<U>
Constructing our Typesafe API Method
Lets define a “constructor” method createAPIMethod
to create a Typesafe fetch
request template.
const createAPIMethod: CreateAPIMethod = function createAPIMethod(opts) {
return async function (input) {
const res = await fetch(opts.url, {
method: opts.method,
body: opts.method === "GET" ? undefined : JSON.stringify(input),
})
return await res.json()
}
}
The purpose of createAPIMethod
is to create a templated fetch request which is fully Typesafe; similar to a class constructor.
Remember, a GET request cannot have a body, which is why I set the request body as undefined for GET.
We will then define a Typesafe API method getPostBodies
to GET data from the jsonplaceholder testing API.
const getPostBodies = createAPIMethod<undefined, { body: string }[]>({
method: "GET",
url: "https://jsonplaceholder.typicode.com/posts",
})
Here we construct an API method by passing in undefined input for GET.
We expect the output to "include" an array of { body: string }
objects.
Next we pass the request method and API URL.
I chose the jsonplaceholder testing API, but this works on all APIs.
Testing our Typesafe API Method
We can test our Typesafe API method by defining a function printPostBodies
to return posts bodies and print them out into an array.
// We create a function to print the bodies of all
// posts returned from the API.
const printPostBodies = async () => {
const bodies = await getPostBodies()
console.log(bodies.map((post) => post.body))
}
printPostBodies()
Here is the expected output when you request the following API endpoint:
→ GET →
Conclusion
Congratulations!
You now have a portable and lightweight fetch
API wrapper that will ensure type safety for every API call you make.
If you enjoyed this article, please make sure to Subscribe, Clap, Comment and Connect with me today! 🌐