rembrembdocs

It is often useful to access the types of your API within your clients. For this purpose, you are able to infer the types contained in your AppRouter.

@trpc/server exports the following helper types to assist with inferring these types from the AppRouter exported by your @trpc/server router:

Inferring Input & Output Types

Let's assume we have this example router:

server.ts

ts

// @filename: server.ts

import { initTRPC } from '@trpc/server';

import { z } from "zod";

const t = initTRPC.create();

const appRouter = t.router({

post: t.router({

`list: t.procedure`

  `.query(() => {`

    `// imaginary db call`

    `return [{ id: 1, title: 'tRPC is the best!' }];`

`}),`

`byId: t.procedure`

  `.input(z.string())`

  `.query((opts) => {`

    `// imaginary db call`

    `return { id: 1, title: 'tRPC is the best!' };`

`}),`

`create: t.procedure`

  `.input(z.object({ title: z.string(), text: z.string(), }))`

  `.mutation((opts) => {`

    `// imaginary db call`

    `return { id: 1, ...opts.input };`

`}),`

}),

});

export type AppRouter = typeof appRouter;

Using the helpers, we can infer the types of our router. The following example shows how to infer the types of the post.create procedure:

client.ts

ts

// @filename: client.ts

import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';

import type { AppRouter } from './server';

type RouterInput = inferRouterInputs<AppRouter>;

type RouterOutput = inferRouterOutputs<AppRouter>;

type PostCreateInput = RouterInput['post']['create'];

       `type PostCreateInput = {     title: string;     text: string; }`

type PostCreateOutput = RouterOutput['post']['create'];

        `type PostCreateOutput = {     title: string;     text: string;     id: number; }`

Infer TRPCClientError types

It's also useful to infer the error type for your AppRouter

client.ts

ts

// @filename: client.ts

import { TRPCClientError } from '@trpc/client';

import type { AppRouter } from './server';

import { trpc } from './trpc';

export function isTRPCClientError(

cause: unknown,

): cause is TRPCClientError<AppRouter> {

return cause instanceof TRPCClientError;

}

async function main() {

try {

`await trpc.post.byId.query('1');`

} catch (cause) {

`if (isTRPCClientError(cause)) {`

  `` // `cause` is now typed as your router's `TRPCClientError` ``

  `console.log('data', cause.data);`

                             `(property) TRPCClientError<BuiltRouter<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }, DecorateCreateRouterOptions<{ post: BuiltRouter<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }, DecorateCreateRouterOptions<...>>; }>>>.data: Maybe<DefaultErrorData>`

`} else {`

  `// [...]`

`}`

}

}

main();