Skip to main content
Version: 10.x

推断类型

在客户端中访问 API 类型通常很有用。为此,你可以推断 AppRouter.h 中包含的类型。

¥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 导出以下辅助程序类型,以帮助从 @trpc/server 路由导出的 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>

推断输入和输出类型

¥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;
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;

使用辅助程序,我们可以推断路由的类型。以下示例显示如何推断 post.create 过程的类型:

¥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; }
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; }

推断 TRPCClientError 类型

¥Infer TRPCClientError types

推断 AppRouter 的错误类型也很有用

¥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<CreateRouterInner<RootConfig<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>, { post: CreateRouterInner<...>; }>>.data: Maybe<DefaultErrorData>
} else {
// [...]
}
}
}
 
main();
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<CreateRouterInner<RootConfig<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>, { post: CreateRouterInner<...>; }>>.data: Maybe<DefaultErrorData>
} else {
// [...]
}
}
}
 
main();