Building Typesafe APIs with tRPC

Ahmed Elsakaan
4 min readJun 10, 2022

--

tRPC is shaping to be a disruptive new technology for building APIs, it’s a framework for creating APIs that are fully typesafe between the client and the server to provide a great developer experience with no need for build steps like code generation.

What is tRPC?

There are two most common ways for building an API currently, REST and GraphQL, if you are using Typescript for your entire stack, you most probably have used a tool like GraphQL Code Generator to provide the API types to your client side, this adds a build step where every time your API changes or your client queries change, you have to rebuild the types and keep them in sync. tRPC aims to fix this issue by being fully typesafe, it especially works really well in monorepo settings where you can import code from your server as that tRPC exports a type that reflects the shape of your API, there is no need anymore for any build steps that way and you are sure your types are in sync with the server.

Creating a tRPC API

It’s very simple and easy to get started making a tRPC API, we firstly need to install some dependencies:

npm install @trpc/server @trpc/client @trpc/react react-query @trpc/next zod

We will assume that we are making the API for a Next.js application but tRPC also supports express.

As a first step, we need to make sure that our tsconfig.json file is in strict mode, this fixes some issues with type safety.

We will then create a ./pages/api/trpc/[trpc].ts file that will catch all the /api/trpc/ requests and let tRPC handle them:

This is an example of creating a tRPC hello router, you can have many routers that get combined that way you can split your API easily. We have a hello query that includes a text property input, we are using zod to validate the input, in this case we want text to be a string that is optional.

In tRPC every query or mutation gets a resolve function that handles the logic of the query/mutation. We are getting our input in the resolve function and returning an object with a greeting property that will either be “hello world” when text is not supplied otherwise it will be hello and then whatever the text supplied is.

This is the most basic tRPC APIexample, as you can see we are exporting a type, this will be used to provide the types for our client, so let’s take a look at that.

Connecting the client to the API

Firstly we will make a ./utils/trpc.ts file that will export all the hooks that we can use for example useQuery and useMutation , very familiar if you are coming from GraphQL, in fact tRPC uses react-query under the hood.

Here we are importing the type we exported in the server route and using it to provide the types to our React hooks.

We now need to setup the client to connect to our API, let’s modify our _app.tsx to do just that:

We have now connected our tRPC server with the client, and we can finally use that useQuery hook in any component that we may have to retrieve the data from our API.

We now should be able to see our component render “Hello client”!

Takeaways

tRPC provides a lot of quality improvements over other ways of creating APIs, there are no more build steps or providing individual types to each query hook to make sure that we aren’t missing anything. It is very simple to start with and extend as you go, it’s also very easy to migrate the API between it’s adapters because the router model always stays the same, currently tRPC supports queries and mutations, support for subscriptions is in beta. I am very excited about what the future holds for tRPC as a project.

--

--

Ahmed Elsakaan

Hey there! I am a full stack web developer from Egypt & a computer science student at Royal Holloway University of London. 🤩