# Inferring Types

> 

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:

```ts title="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:

```ts title="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;
// }
```

## Inferring Individual Procedure Types

If you already have access to a specific procedure on your router, you can infer its input or output directly:

```ts title="client.ts"
import type {
  inferProcedureInput,
  inferProcedureOutput,
} from '@trpc/server';
import type { AppRouter } from './server';

type PostByIdInput = inferProcedureInput<AppRouter['post']['byId']>;
// type PostByIdInput = string
type PostByIdOutput = inferProcedureOutput<AppRouter['post']['byId']>;
// type PostByIdOutput = {
//     id: number;
//     title: string;
// }
```

For subscriptions, you can infer the subscription input and the emitted data type:

```ts title="client.ts"
import type {
  inferSubscriptionInput,
  inferSubscriptionOutput,
} from '@trpc/server';
import type { AppRouter } from './server';

type OnPostAddInput = inferSubscriptionInput<AppRouter['post']['onPostAdd']>;
// type OnPostAddInput = {
//     authorId: string;
// }
type OnPostAddOutput = inferSubscriptionOutput<AppRouter['post']['onPostAdd']>;
// type OnPostAddOutput = {
//     id: number;
//     title: string;
//     authorId: string;
// }
```

## Infer `TRPCClientError` types

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

```ts title="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();
```
