先に要点
- tRPC は TypeScript 用の 型安全な API ライブラリ。サーバが定義した型を クライアント側で直接インポート できるため、「OpenAPI / GraphQL スキーマを生成して同期する」 ような工程が不要。
- API 呼び出しは client.user.byId.query({ id: 1 }) のように 「関数を呼ぶ感覚」 で書ける。レスポンスの型も自動で導出されるので、「API レスポンスの型を別に書く」 作業がゼロになる。
- Zod による入力検証、pnpm workspaces によるモノレポ、Vercel へのデプロイ、というモダン TS スタックの中心に位置するライブラリ。
- 万能ではない。「 外部に公開する API」 「非 TypeScript クライアント」 が前提なら REST / GraphQL の方が向く。tRPC は基本 「サーバとクライアントを両方自社の TS で書く案件」 に最適化されている。
tRPC ってよく聞くけど、結局 REST と何が違うの? GraphQL でいいのでは? 「モノレポなら使うべき?」 ── TypeScript フルスタックで開発する案件が増えるほど、tRPC の名前は外せない存在になってきました。
ざっくり言うと、tRPC は サーバが書いた TypeScript 型を、クライアントから直接 import して呼び出せる ことを最大の売りにした API ライブラリです。 OpenAPI のスキーマ定義や GraphQL の SDL を介さず、TypeScript の型システムをそのまま API 契約として使う という割り切りで、「型を書く時間 = API 契約を書く時間」 という体験を実現します。
この記事では、2026年5月時点の tRPC を、「何を解決するのか・REST / GraphQL との違い・どう書くのか・どこで効くか・どこでは向かないか」 の順で整理します。
tRPC が解決した問題
「なぜ tRPC が広まったか」 は、フロントエンドエンジニアが 「API 開発のたびに同じ作業をしている」 という不満の歴史を見ると分かります。
①型を二重に書く
サーバで 「User」 型を書き、フロントでも 「ApiUser」 型を書く。「OpenAPI を生成してジェネレータを回す」 という選択肢もあるが、ビルドの一手間と微妙にずれる型が問題になる。
② エンドポイントの構造を覚える必要がある
「GET /api/users/:id」 を覚え、「fetch」 で叩き、JSON をパースし、型を当てる ─ という同じ作業を毎回書く。「シンプルだが面倒」 が積み重なる。
④ TypeScript の表現力を使い切れない
OpenAPI / GraphQL は TS より表現力が低い。「ユニオン型」 「条件付き型」 などの強い型情報が、API 境界で失われがち。
tRPC は サーバとクライアントが同じリポジトリ(or モノレポ)にあるなら、TS 型をそのまま共有すればいいじゃないか という、ある意味で開き直った発想で、これらの問題を一気に解消しました。
基本の使い方 — 「Procedure」 と 「Router」
最小例で雰囲気を確認します。
// server/router.ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.create();
export const appRouter = t.router({
user: t.router({
byId: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return await db.user.findUnique({ where: { id: input.id } });
}),
create: t.procedure
.input(z.object({ name: z.string(), email: z.string().email() }))
.mutation(async ({ input }) => {
return await db.user.create({ data: input });
}),
}),
});
export type AppRouter = typeof appRouter;
クライアント側はこうなります。
// client.ts
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server/router';
const trpc = createTRPCProxyClient<AppRouter>({
links: [httpBatchLink({ url: '/trpc' })],
});
const user = await trpc.user.byId.query({ id: '42' });
const created = await trpc.user.create.mutate({ name: 'Alice', email: 'a@example.com' });
ポイント:
- サーバの 「AppRouter」 型を クライアントが 「import type」 するだけ で、利用できるエンドポイント、引数、戻り値の型が完全に揃う。
- 「query」 は GET 系の参照、「mutation」 は POST/PUT/DELETE 系の更新、と概念的に分ける。
- 入力検証は Zod をそのまま使う(Yup / Valibot 等もアダプタ経由で可)。
「スキーマ生成のコマンドを叩く必要がない」 のが、地味だが体験を大きく変える点です。
REST / GraphQL との比較
3つを並べると、それぞれの立ち位置が見えやすくなります。
| 軸 | REST | GraphQL | tRPC |
|---|---|---|---|
| API 契約の形 | OpenAPI(別途定義) | SDL(別途定義) | TypeScript の型(自動) |
| クライアントの呼び方 | HTTP リクエスト | クエリ文字列 + 変数 | 関数呼び出し |
| 型生成 | codegen が必要 | codegen が必要 | 不要(import するだけ) |
| 外部公開向き | ◎(標準) | ○(SDL があれば多言語OK) | ×(TS 前提) |
| クライアントの言語 | 何でもOK | 何でもOK | TypeScript のみ |
| サーバ↔フロントが同じ TS | 普通 | 普通 | 圧倒的に楽 |
| クエリの柔軟性 | 低(エンドポイント固定) | 高(クライアントが選ぶ) | 中(サーバが procedure を提供) |
| ツール / ドキュメント | 豊富 | 豊富 | TS スタック向きに豊富 |
要点は 「 API を誰が・何で呼ぶか」 で選ぶ:
「どれが優れているか」 ではなく、「案件の境界条件にどれが合うか」 で決める道具立てです。
React Query との統合
tRPC が普段使いで快適に感じるもう1つの理由が、React Query(TanStack Query)との深い統合 です。
// 通常版 React Query を意識せずに使える
const { data, isLoading, error } = trpc.user.byId.useQuery({ id: '42' });
const create = trpc.user.create.useMutation({
onSuccess: () => {
trpc.user.byId.invalidate({ id: '42' });
},
});
「fetch を直接書く / axios を呼ぶ」 が、「React Query のフック + 型安全な引数 + 自動キャッシュ無効化」 に置き換わります。 キャッシュ、リトライ、optimistic update など React Query の機能はそのまま使え、「データ取得の標準的なコードベース」 が一気に手に入る、というのが現場の体感です。
どこで効くか — tRPC が活きる案件
実務で 「tRPC を選んでよかった」 となる構成は、おおむね決まっています。
①Next.js + 自社 TypeScript フルスタック
Next.js の App Router / Pages Router の API レイヤを tRPC で組む構成は最頻出。「サーバ側のコードを書く感覚で API が完成」 する。
② モノレポでサーバとクライアントを並走
pnpm workspaces や Turborepo で 「apps/web」 と 「apps/api」 を並べる構成と相性◎。「同じ型を共有」 が物理ファイルとして自然に成立する。
③ 小〜中規模スタートアップ
「 早く作って・早く出す」 が求められるフェーズで、「API スキーマの整備」 を後回しにしても型安全を保てる。MVP〜スケール初期で抜群に効く。
④ 社内ツール / 管理画面
外部 API としての公開が不要で、TS で書く社内システムなら、tRPC で書かない理由がほぼない。
「完全に内向きの TS スタック」 のときに、tRPC は最も大きな威力を発揮します。 逆に 「 外向きの API として公開する」 場合は、後述のように tRPC ではなく REST / GraphQL の方が自然 です。
どこでは向かないか — tRPC の限界
「流行っているから tRPC」 で選ぶと、後で痛い目を見る場面もあります。
② モバイルや別言語クライアント
iOS / Android / Go / Rust など TypeScript 以外のクライアントを想定する場合、tRPC は使えない / 旨味がない。「type を import する」 が成立しないため。
④ 非常に複雑なクエリ要件
「 1画面で 30 種類のデータを取得し、フィルタや並びをクライアント側で柔軟に選ぶ」 のような GraphQL の本来の強みが効く案件は、GraphQL のほうが向く。
「内向き TS なら tRPC、外向きや複雑な要件なら別」 という判断軸を持っておくと、選定で迷いが減ります。
認証・認可・ミドルウェア
tRPC は procedure ミドルウェア という仕組みで、認証・認可・ロギング・レート制御などを共通化できます。
const isAuthed = t.middleware(async ({ ctx, next }) => {
if (!ctx.user) throw new Error('UNAUTHORIZED');
return next({ ctx: { ...ctx, user: ctx.user } });
});
export const protectedProcedure = t.procedure.use(isAuthed);
// 使うとき
export const appRouter = t.router({
me: protectedProcedure.query(({ ctx }) => ctx.user),
});
「保護したい procedure は protectedProcedure を使う」 と決めるだけで、認証チェックが一律にかかる、という設計です。 HTTP ステータスコードの記事 で触れた 「401 / 403 を返す境界」 を、tRPC では `エラーコード(「UNAUTHORIZED」 「FORBIDDEN」)」 として表現できる仕組みも持っています。
モノレポでの典型構成
tRPC が真価を発揮するのは、モノレポでの構成です。
「API の追加 = サーバの router にメソッドを増やす」 だけで、クライアント側は即座に補完が効く ─ という体験が、現代の TS フルスタックにおける tRPC の魅力の核心です。
AI 時代の tRPC 観
AI を組み込んだ TS アプリでも、tRPC の役割は重要になっています。
AI 呼び出しの型安全
「 AI に何を投げて、何が返ってくるか」 を Zod スキーマで宣言し、tRPC の procedure として公開する。フロントから 「trpc.ai.summarize.useMutation」 のような自然な呼び出しが可能になる。
ストリーミングと相性
「 tRPC + React Query の streaming」 で、「AI が応答を生成する過程」 を UI にリアルタイム反映するのが楽。LLM のストリーミング応答に向いた構成。
「小さなチームが AI で爆速に開発する」 文脈で、tRPC は事実上のスタンダードのひとつになっています。 「内向き / TypeScript / モノレポ」 が揃った瞬間に、tRPC の合理性は最大化される、というのが2026年現在の景色です。
tRPC に関するよくある質問
Q. tRPC は本番運用に耐えますか?
A. 十分耐えています。Vercel・Cal.com・PlanetScale など多くの著名プロダクトで本番採用実績があり、「v10」 以降は安定して使われています。設計が割り切られているがゆえに、ライブラリとしての複雑性は小さく、運用上のトラブルは少なめというのが現場の評価です。
Q. REST / GraphQL を捨てて全部 tRPC にすべきですか?
A. いいえ。内向きは tRPC、外向き API は REST / GraphQL の使い分けが現実的です。同じ会社の中で、「社内ツールは tRPC、公開 API は REST」 という二刀流の構成も普通にあります。
Q. Zod は必須ですか?
A. 必須ではないですが、「事実上の標準コンビ」 です。Zod を使うと 「 入力検証 + 型推論 + tRPC procedure の型」 が全部1つの定義で済む ので、これを採用しないのはむしろ手間が増えやすいです。Valibot などのアダプタも存在します。
Q. SSR / Next.js での扱いはどうなりますか?
A. tRPC は Next.js を一級サポート しています。「@trpc/next」 で SSR / SSG / RSC との統合を提供し、「サーバコンポーネントから直接 procedure を呼ぶ」 ような構成も可能です。Next.js + tRPC は現在の TS フルスタック開発で頻出するセットです。
Q. パフォーマンスは REST より劣りますか?
A. 大差ありません。HTTP の上で動く JSON 通信 という意味では REST と同等のオーバーヘッドで、`バッチング(「httpBatchLink」)」 で複数 procedure をまとめて送ることで、むしろ通信回数を減らせる場面もあります。
Q. tRPC の学習コストはどのくらい?
A. TypeScript と Zod を知っていれば、半日〜1日で書き始められる 程度です。「procedure / router / client / React Query」 の4語と、「query / mutation / input / output」 の4語を押さえれば、最初のエンドポイントは作れます。
Q. tRPC を採用すると、技術ロックインは厳しいですか?
A. ある程度はあります。「tRPC で書いた procedure を REST にエクスポート」 するアダプタもありますが、設計の根っこは TS の型共有前提なので、「完全に別技術に移行する」 ときは書き直しに近い作業が発生します。これも 「内向きの内製案件で使う」 という前提なら問題になりにくい、というのが多くの判断です。