Inferring Types
It is often useful to wrap functionality of your @trpc/client
or @trpc/react-query
api within other functions. For this purpose, it's necessary to be able to infer input types and output types generated by your @trpc/server
router.
Inference Helpers​
@trpc/server
exports the following helper types to assist with inferring these types from the AppRouter
exported by your @trpc/server
router:
inferProcedureOutput<TProcedure>
inferProcedureInput<TProcedure>
Let's assume we have this example router:
server.tsts
// @filename: server.tsimport {initTRPC } from '@trpc/server';import {z } from "zod";Âconstt =initTRPC .create ();ÂconstappRouter =t .router ({post :t .router ({byId :t .procedure .input (z .string ()).query (({input }) => {// imaginary db callreturn {id : 1,title : 'tRPC is the best!' };}),create :t .procedure .input (z .object ({title :z .string (),text :z .string (), })).mutation (({input }) => {// imaginary db callreturn {id : 1, ...input };}),}),});Âexport typeAppRouter = typeofappRouter ;
server.tsts
// @filename: server.tsimport {initTRPC } from '@trpc/server';import {z } from "zod";Âconstt =initTRPC .create ();ÂconstappRouter =t .router ({post :t .router ({byId :t .procedure .input (z .string ()).query (({input }) => {// imaginary db callreturn {id : 1,title : 'tRPC is the best!' };}),create :t .procedure .input (z .object ({title :z .string (),text :z .string (), })).mutation (({input }) => {// imaginary db callreturn {id : 1, ...input };}),}),});Âexport typeAppRouter = typeofappRouter ;
By traversing the router object, you can infer the types of the procedures. The following example shows how to infer the types of the procedures using the example appRouter
:
client.tsts
// @filename: client.tsimport type {inferProcedureInput ,inferProcedureOutput } from '@trpc/server';import type {AppRouter } from './server';ÂtypePostCreateInput =inferProcedureInput <AppRouter ['post']['create']>;typePostCreateOutput =inferProcedureOutput <AppRouter ['post']['create']>;
client.tsts
// @filename: client.tsimport type {inferProcedureInput ,inferProcedureOutput } from '@trpc/server';import type {AppRouter } from './server';ÂtypePostCreateInput =inferProcedureInput <AppRouter ['post']['create']>;typePostCreateOutput =inferProcedureOutput <AppRouter ['post']['create']>;
Additional DX Helper Type​
If you don't like the double-import from the above snippet, @trpc/server
also exports a type GetInferenceHelpers<TRouter>
. This lets you pass your router once at initialization, then import a single helper type when inferring types:
utils/trpc.tsts
import type {GetInferenceHelpers } from '@trpc/server';import type {AppRouter } from './server';Âexport typeInferProcedures =GetInferenceHelpers <AppRouter >;
utils/trpc.tsts
import type {GetInferenceHelpers } from '@trpc/server';import type {AppRouter } from './server';Âexport typeInferProcedures =GetInferenceHelpers <AppRouter >;
ts
export typeAppRouterTypes =GetInferenceHelpers <AppRouter >;ÂtypePostCreate =AppRouterTypes ['post']['create'];ÂtypePostCreateInput =PostCreate ['input'];typePostCreateOutput =PostCreate ['output'];
ts
export typeAppRouterTypes =GetInferenceHelpers <AppRouter >;ÂtypePostCreate =AppRouterTypes ['post']['create'];ÂtypePostCreateInput =PostCreate ['input'];typePostCreateOutput =PostCreate ['output'];
Infer TRPClientError
s based on your router​
client.tsts
// @filename: client.tsimport {TRPCClientError } from '@trpc/client';import type {AppRouter } from './server';import {trpc } from './trpc';Âexport functionisTRPCClientError (cause : unknown,):cause isTRPCClientError <AppRouter > {returncause instanceofTRPCClientError ;}Âasync functionmain () {try {awaittrpc .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 ();
client.tsts
// @filename: client.tsimport {TRPCClientError } from '@trpc/client';import type {AppRouter } from './server';import {trpc } from './trpc';Âexport functionisTRPCClientError (cause : unknown,):cause isTRPCClientError <AppRouter > {returncause instanceofTRPCClientError ;}Âasync functionmain () {try {awaittrpc .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 ();