プログラミング フレームワーク ソフトウェア 公開日 2026.05.15 更新日 2026.05.15

tRPC とは何か?TypeScript で型安全な API を作る仕組みと REST / GraphQL との使い分け

tRPC は TypeScript で `スキーマ生成も OpenAPI もなしで、サーバとクライアントが完全に型共有する API』を作るためのライブラリです。Zod での入力検証、React Query との統合、Next.js / モノレポでの典型構成、REST / GraphQL との使い分けまで、`なぜ流行ったのか』 を実務目線で整理します。

先に要点

  • tRPCTypeScript 用の ` 型安全な 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 して呼び出せる』</strong> ことを最大の売りにした API ライブラリです。 OpenAPI のスキーマ定義や GraphQL の SDL を介さず、<strong> TypeScript の型システムをそのまま API 契約として使う』 という割り切りで、`型を書く時間 = API 契約を書く時間』 という体験を実現します。

この記事では、2026年5月時点の tRPC を、`何を解決するのか・REST / GraphQL との違い・どう書くのか・どこで効くか・どこでは向かないか』 の順で整理します。

tRPC が解決した問題

なぜ tRPC が広まったか』 は、フロントエンドエンジニアが API 開発のたびに同じ作業をしている』 という不満の歴史を見ると分かります。

①型を二重に書く

サーバで `User』 型を書き、フロントでも `ApiUser』 型を書く。`OpenAPI を生成してジェネレータを回す』 という選択肢もあるが、ビルドの一手間と微妙にずれる型が問題になる。

エンドポイントの構造を覚える必要がある

`GET /api/users/:id』 を覚え、`fetch』 で叩き、JSON をパースし、型を当てる ─ という同じ作業を毎回書く。`シンプルだが面倒』 が積み重なる。

③ スキーマと実装がずれる

OpenAPI / GraphQL の SDL を更新し忘れると、フロントとバックの認識がずれる。` API ドキュメントは古くなる』 問題が構造的に発生。

TypeScript の表現力を使い切れない

OpenAPI / GraphQLTS より表現力が低い。`ユニオン型』 `条件付き型』 などの強い型情報が、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』 型を <strong>クライアントが 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 を誰が・何で呼ぶか』 で選ぶ:

  • 外部に公開、複数言語クライアント → REST
  • 大規模、複雑なクエリ要件、複数チーム → GraphQL
  • 内製、サーバもクライアントも TypeScript → tRPC

どれが優れているか』 ではなく、案件の境界条件にどれが合うか』 で決める道具立てです。

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 は最も大きな威力を発揮します。 逆に <strong> 外向きの API として公開する』 場合は、後述のように tRPC ではなく REST / GraphQL の方が自然 です。

どこでは向かないか — tRPC の限界

`流行っているから tRPC』 で選ぶと、後で痛い目を見る場面もあります。

①外部公開 API

API ドキュメントを世間に公開して、サードパーティが叩く前提の API は、tRPC では難しい。`REST + OpenAPI』 のほうが標準化されており、SDK 配布も楽。

② モバイルや別言語クライアント

iOS / Android / Go / Rust など TypeScript 以外のクライアントを想定する場合、tRPC は使えない / 旨味がない。`type を import する』 が成立しないため。

③ 巨大なフロントチーム × 専任バックエンド

` フロントとバックが完全に別の組織 / 別の技術スタック』 だと、tRPC の `型共有』 のメリットが失われる。GraphQL / REST + 明示的なスキーマの方が運用しやすい。

④ 非常に複雑なクエリ要件

` 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 ステータスコードの記事](/articles/representative-http-status-codes-explained) で触れた 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 で UI を作る([v0 / Vercel](/articles/what-is-v0-vercel-ai-ui-generator-usage))と、その UI が叩く API を tRPC で爆速に書ける、というコンビは MVP の速度を一段押し上げる。

フルスタック TS の重要性

AI 時代に「JS / TS 1 言語でフロントとバックを書く」価値が更に上がる。tRPC は ` その重要性に最も乗っているライブラリ』と言っても言い過ぎではない。

小さなチームが AI で爆速に開発する』 文脈で、tRPC は事実上のスタンダードのひとつになっています。 内向き / TypeScript / モノレポ』 が揃った瞬間に、tRPC の合理性は最大化される、というのが2026年現在の景色です。

tRPC に関するよくある質問

Q. tRPC は本番運用に耐えますか?

A. 十分耐えています。Vercel・Cal.com・PlanetScale など多くの著名プロダクトで本番採用実績があり、v10』 以降は安定して使われています。<strong> 設計が割り切られているがゆえに、ライブラリとしての複雑性は小さく、運用上のトラブルは少なめ』というのが現場の評価です。

Q. REST / GraphQL を捨てて全部 tRPC にすべきですか?

A. いいえ。 内向きは tRPC、外向き API は REST / GraphQL』</strong> の使い分けが現実的です。同じ会社の中で、社内ツールは tRPC、公開 API は REST』 という二刀流の構成も普通にあります。

Q. Zod は必須ですか?

A. 必須ではないですが、事実上の標準コンビ』 です。Zod を使うと <strong> 入力検証 + 型推論 + 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 通信』</strong> という意味では REST と同等のオーバーヘッドで、バッチング(`httpBatchLink』)』 で複数 procedure をまとめて送ることで、むしろ通信回数を減らせる場面もあります。

Q. tRPC の学習コストはどのくらい?

A. TypeScript と Zod を知っていれば、半日〜1日で書き始められる』</strong> 程度です。procedure / router / client / React Query』 の4語と、`query / mutation / input / output』 の4語を押さえれば、最初のエンドポイントは作れます。

Q. tRPC を採用すると、技術ロックインは厳しいですか?

A. ある程度はあります。tRPC で書いた procedure を REST にエクスポート』 するアダプタもありますが、設計の根っこは TS の型共有前提なので、完全に別技術に移行する』 ときは書き直しに近い作業が発生します。これも `内向きの内製案件で使う』 という前提なら問題になりにくい、というのが多くの判断です。

参考リンク

あとで見返すならここで保存

読み終わったあとに残しておきたい記事は、お気に入りからまとめて辿れます。