クイックスタート
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
インストール
tRPCは複数のパッケージに分割されているため、必要なものだけをインストールできます。適切なコードベースのセクションにパッケージをインストールしてください。このクイックスタートガイドではシンプルに保つため、バニラクライアントのみを使用します。フレームワーク別ガイドについては、Reactでの使用方法とNext.jsでの使用方法をご覧ください。
- tRPCにはTypeScript >=5.7.2が必要です
tsconfig.jsonで"strict": trueを使用することを強く推奨します。非strictモードは公式にサポートしていません
まず、@trpc/serverと@trpc/clientパッケージをインストールします:
- npm
- yarn
- pnpm
- bun
- deno
npm install @trpc/server @trpc/client
yarn add @trpc/server @trpc/client
pnpm add @trpc/server @trpc/client
bun add @trpc/server @trpc/client
deno add npm:@trpc/server npm:@trpc/client
AIコーディングエージェントをご利用の場合、より良いコード生成のためにtRPCスキルをインストールしてください:
bashnpx @tanstack/intent@latest install
bashnpx @tanstack/intent@latest install
初めてのtRPC API
tRPCで型安全なAPIを構築する手順を見ていきましょう。最初に、このAPIには以下のTypeScriptシグネチャを持つ3つのエンドポイントが含まれます:
tstype User = { id: string; name: string; };userList: () => User[];userById: (id: string) => User;userCreate: (data: { name: string }) => User;
tstype User = { id: string; name: string; };userList: () => User[];userById: (id: string) => User;userCreate: (data: { name: string }) => User;
以下が構築するファイル構造です。循環依存を防ぐため、tRPCの初期化、ルーター定義、サーバー設定は別々のファイルに分離することを推奨します:
.├── server/│ ├── trpc.ts # tRPC instantiation & setup│ ├── appRouter.ts # Your API logic and type export│ └── index.ts # HTTP server└── client/└── index.ts # tRPC client
.├── server/│ ├── trpc.ts # tRPC instantiation & setup│ ├── appRouter.ts # Your API logic and type export│ └── index.ts # HTTP server└── client/└── index.ts # tRPC client
1. ルーターインスタンスの作成
まずtRPCバックエンドを初期化します。tRPCオブジェクト全体ではなく、再利用可能なヘルパー関数をエクスポートするために、別ファイルで行うのが良い慣習です。
server/trpc.tstsimport {initTRPC } from '@trpc/server';/*** Initialization of tRPC backend* Should be done only once per backend!*/constt =initTRPC .create ();/*** Export reusable router and procedure helpers* that can be used throughout the router*/export constrouter =t .router ;export constpublicProcedure =t .procedure ;
server/trpc.tstsimport {initTRPC } from '@trpc/server';/*** Initialization of tRPC backend* Should be done only once per backend!*/constt =initTRPC .create ();/*** Export reusable router and procedure helpers* that can be used throughout the router*/export constrouter =t .router ;export constpublicProcedure =t .procedure ;
次に、メインのルーターインスタンス(通常appRouterと呼ばれます)を初期化し、後でプロシージャを追加します。最後に、クライアント側で後ほど使用するルーターの型をエクスポートする必要があります。
server/appRouter.tstsimport {router } from './trpc';export constappRouter =router ({// ...});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {router } from './trpc';export constappRouter =router ({// ...});export typeAppRouter = typeofappRouter ;
2. クエリプロシージャの追加
ルーターにクエリプロシージャを追加するにはpublicProcedure.query()を使用します。
以下はuserListというクエリプロシージャを作成し、ユーザーリストを返す例です:
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({userList :publicProcedure .query (async () => {constusers :User [] = [{id : '1',name : 'Katt' }];returnusers ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({userList :publicProcedure .query (async () => {constusers :User [] = [{id : '1',name : 'Katt' }];returnusers ;}),});export typeAppRouter = typeofappRouter ;
3. 入力パーサーを使用したプロシージャ入力の検証
userByIdプロシージャを実装するには、クライアントからの入力を受け入れる必要があります。tRPCでは入力パーサーを定義して入力を検証・解析できます。独自の入力パーサーを定義するか、zod、yup、superstructなどの検証ライブラリを使用できます。
入力パーサーはpublicProcedure.input()で定義し、下記のようにリゾルバー関数からアクセスできます:
- Vanilla
- Zod
- Yup
- Valibot
The input parser should be a function that validates and casts the input of this procedure. It should return a strongly typed value when the input is valid or throw an error if the input is invalid.
Throughout the remainder of this documentation, we will use zod as our validation library.
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({// ...userById :publicProcedure // The input is unknown at this time. A client could have sent// us anything so we won't assume a certain data type..input ((val : unknown) => {// If the value is of type string, return it.// It will now be inferred as a string.if (typeofval === 'string') returnval ;// Uh oh, looks like that input wasn't a string.// We will throw an error instead of running the procedure.throw newError (`Invalid input: ${typeofval }`);}).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({// ...userById :publicProcedure // The input is unknown at this time. A client could have sent// us anything so we won't assume a certain data type..input ((val : unknown) => {// If the value is of type string, return it.// It will now be inferred as a string.if (typeofval === 'string') returnval ;// Uh oh, looks like that input wasn't a string.// We will throw an error instead of running the procedure.throw newError (`Invalid input: ${typeofval }`);}).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
The input parser can be any ZodType, e.g. z.string() or z.object().
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import {z } from 'zod';export constappRouter =router ({// ...userById :publicProcedure .input (z .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import {z } from 'zod';export constappRouter =router ({// ...userById :publicProcedure .input (z .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
The input parser can be any YupSchema, e.g. yup.string() or yup.object().
Throughout the remainder of this documentation, we will use zod as our validation library.
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import * asyup from 'yup';export constappRouter =router ({// ...userById :publicProcedure .input (yup .string ().required ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import * asyup from 'yup';export constappRouter =router ({// ...userById :publicProcedure .input (yup .string ().required ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
The input parser can be any Valibot schema, e.g. v.string() or v.object().
Throughout the remainder of this documentation, we will use zod as our validation library.
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import * asv from 'valibot';export constappRouter =router ({// ...userById :publicProcedure .input (v .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';import * asv from 'valibot';export constappRouter =router ({// ...userById :publicProcedure .input (v .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),});export typeAppRouter = typeofappRouter ;
4. ミューテーションプロシージャの追加
GraphQLと同様に、tRPCはQueryプロシージャとMutationプロシージャを区別します。
QueryとMutationの違いは主に意味論的なものです。QueryはHTTP GETを使用し読み取り操作を意図し、MutationはHTTP POSTを使用し副作用を伴う操作を意図します。
ルーターオブジェクトに新しいプロパティとしてuserCreateミューテーションを追加しましょう:
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({// ...userCreate :publicProcedure .input (z .object ({name :z .string () })).mutation (async (opts ) => {const {input } =opts ;// Create the user in your DBconstuser :User = {id : '1', ...input };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {publicProcedure ,router } from './trpc';export constappRouter =router ({// ...userCreate :publicProcedure .input (z .object ({name :z .string () })).mutation (async (opts ) => {const {input } =opts ;// Create the user in your DBconstuser :User = {id : '1', ...input };returnuser ;}),});export typeAppRouter = typeofappRouter ;
APIの提供
ルーターを定義したので、提供できます。tRPCには主要なWebサーバー向けのファーストクラスアダプターがあります。シンプルにするため、ここではNode.js向けstandaloneアダプターを使用します。
server/index.tstsimport {createHTTPServer } from '@trpc/server/adapters/standalone';import {appRouter } from './appRouter';constserver =createHTTPServer ({router :appRouter ,});server .listen (3000);
server/index.tstsimport {createHTTPServer } from '@trpc/server/adapters/standalone';import {appRouter } from './appRouter';constserver =createHTTPServer ({router :appRouter ,});server .listen (3000);
See the full backend code
server/trpc.tstsimport {initTRPC } from '@trpc/server';constt =initTRPC .create ();export constrouter =t .router ;export constpublicProcedure =t .procedure ;
server/trpc.tstsimport {initTRPC } from '@trpc/server';constt =initTRPC .create ();export constrouter =t .router ;export constpublicProcedure =t .procedure ;
server/appRouter.tstsimport {z } from "zod";import {publicProcedure ,router } from "./trpc";typeUser = {id : string;name : string };export constappRouter =router ({userList :publicProcedure .query (async () => {constusers :User [] = [{id : '1',name : 'Katt' }];returnusers ;}),userById :publicProcedure .input (z .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),userCreate :publicProcedure .input (z .object ({name :z .string () })).mutation (async (opts ) => {const {input } =opts ;constuser :User = {id : '1', ...input };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/appRouter.tstsimport {z } from "zod";import {publicProcedure ,router } from "./trpc";typeUser = {id : string;name : string };export constappRouter =router ({userList :publicProcedure .query (async () => {constusers :User [] = [{id : '1',name : 'Katt' }];returnusers ;}),userById :publicProcedure .input (z .string ()).query (async (opts ) => {const {input } =opts ;constuser :User = {id :input ,name : 'Katt' };returnuser ;}),userCreate :publicProcedure .input (z .object ({name :z .string () })).mutation (async (opts ) => {const {input } =opts ;constuser :User = {id : '1', ...input };returnuser ;}),});export typeAppRouter = typeofappRouter ;
server/index.tstsimport {createHTTPServer } from "@trpc/server/adapters/standalone";import {appRouter } from "./appRouter";constserver =createHTTPServer ({router :appRouter ,});server .listen (3000);
server/index.tstsimport {createHTTPServer } from "@trpc/server/adapters/standalone";import {appRouter } from "./appRouter";constserver =createHTTPServer ({router :appRouter ,});server .listen (3000);
クライアント側での新しいバックエンドの使用
クライアントサイドのコードに移り、エンドツーエンドのタイプセーフティの力を実感しましょう。クライアントで使用するためにAppRouter型をインポートするだけで、実装の詳細をクライアントに漏らすことなくシステム全体の完全なタイプセーフティを実現できます。
1. tRPCクライアントのセットアップ
client/index.tstsimport {createTRPCClient ,httpBatchLink } from '@trpc/client';import type {AppRouter } from './appRouter';// 👆 **type-only** imports are stripped at build time// Pass AppRouter as a type parameter. 👇 This lets `trpc` know// what procedures are available on the server and their input/output types.consttrpc =createTRPCClient <AppRouter >({links : [httpBatchLink ({url : 'http://localhost:3000',}),],});
client/index.tstsimport {createTRPCClient ,httpBatchLink } from '@trpc/client';import type {AppRouter } from './appRouter';// 👆 **type-only** imports are stripped at build time// Pass AppRouter as a type parameter. 👇 This lets `trpc` know// what procedures are available on the server and their input/output types.consttrpc =createTRPCClient <AppRouter >({links : [httpBatchLink ({url : 'http://localhost:3000',}),],});
tRPCのリンクはGraphQLのリンクと似ており、サーバーへのデータフローを制御できます。上記の例ではhttpBatchLinkを使用しており、複数の呼び出しを自動的に単一のHTTPリクエストにバッチ処理します。リンクの詳細な使用法については、リンクドキュメントを参照してください。
2. 型推論とオートコンプリート
これでtrpcオブジェクトを通じてAPIプロシージャにアクセスできます。実際に試してみましょう!
client/index.tsts// Inferred typesconstuser = awaittrpc .userById .query ('1');constcreatedUser = awaittrpc .userCreate .mutate ({name : 'Katt' });
client/index.tsts// Inferred typesconstuser = awaittrpc .userById .query ('1');constcreatedUser = awaittrpc .userCreate .mutate ({name : 'Katt' });
クライアント側でオートコンプリートを使用してAPIを探索することもできます
client/index.tststrpc .u ;
client/index.tststrpc .u ;
次のステップ
| What's next? | Description |
|---|---|
| Example Apps | Explore tRPC in your chosen framework |
| TanStack React Query | Recommended React integration via @trpc/tanstack-react-query |
| Next.js | Usage with Next.js |
| Server Adapters | Express, Fastify, and more |
| Transformers | Use superjson to retain complex types like Date |