Inferring Types
On this page
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:
inferRouterInputs<TRouter>inferRouterOutputs<TRouter>inferProcedureInput<TProcedure>inferProcedureOutput<TProcedure>inferSubscriptionInput<TProcedure>inferSubscriptionOutput<TProcedure>
Inferring Input & Output Types
Let's assume we have this example router:
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 };
}),
onPostAdd: t.procedure
.input(z.object({ authorId: z.string() }))
.subscription(async function* ({ input }) {
// imaginary event source
yield {
id: 1,
title: 'tRPC is the best!',
authorId: input.authorId,
};
}),
}),
});
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
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 PostCreateOutput = RouterOutput['post']['create'];Inferring Individual Procedure Types
If you already have access to a specific procedure on your router, you can infer its input or output directly:
client.ts
import type {
inferProcedureInput,
inferProcedureOutput,
} from '@trpc/server';
import type { AppRouter } from './server';
type PostByIdInput = inferProcedureInput<AppRouter['post']['byId']>;
type PostByIdOutput = inferProcedureOutput<AppRouter['post']['byId']>;For subscriptions, you can infer the subscription input and the emitted data type:
client.ts
import type {
inferSubscriptionInput,
inferSubscriptionOutput,
} from '@trpc/server';
import type { AppRouter } from './server';
type OnPostAddInput = inferSubscriptionInput<AppRouter['post']['onPostAdd']>;
type OnPostAddOutput = inferSubscriptionOutput<AppRouter['post']['onPostAdd']>;Infer TRPCClientError types
It's also useful to infer the error type for your AppRouter
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);
} else {
// [...]
}
}
}
main();