フルスタック TypeScript 開発において、フロントエンドとバックエンド間の型定義の同期は長年の課題であった。REST API では OpenAPI スキーマを、GraphQL ではスキーマ定義言語を別途管理する必要があり、型の不整合がランタイムエラーの温床となってきた。tRPC(TypeScript Remote Procedure Call)は、この問題を根本から解決するフレームワークとして、2025年以降のフルスタック開発で急速に採用が進んでいる。
tRPC とは何か
tRPC は、バックエンドで定義した関数をフロントエンドから直接呼び出せるようにするフレームワークである。最大の特徴は、スキーマ定義言語やコード生成を必要とせず、TypeScript の型推論機能を活用してエンドツーエンドの型安全性を実現する点にある。
従来のアプローチでは、以下のような手順が必要だった。
- API エンドポイントを定義
- リクエスト/レスポンスの型を定義
- フロントエンド用のクライアントコードを生成
- 変更のたびに再生成と同期
tRPC では、バックエンドで関数を定義するだけで、フロントエンドは即座にその関数の引数と戻り値の型を認識できる。コード生成は不要であり、ビルドステップも追加されない。
基本的な使い方
tRPC の基本的な構成要素は「プロシージャ」である。プロシージャには3種類がある。
- Query:データの取得(GET相当)
- Mutation:データの変更(POST/PUT/DELETE相当)
- Subscription:リアルタイム更新(WebSocket)
バックエンド側でルーターを定義する例を示す。
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return await db.user.findUnique({ where: { id: input.id } });
}),
createUser: 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;
フロントエンドからは、この関数を直接呼び出すように使用できる。
import { trpc } from './utils/trpc';
// TypeScript が自動的に引数と戻り値の型を推論
const user = await trpc.getUser.query({ id: '123' });
// user.name, user.email などの型が自動補完される
const newUser = await trpc.createUser.mutate({
name: 'John',
email: 'john@example.com'
});
REST/GraphQL との比較
tRPC を従来のアプローチと比較すると、以下の違いがある。
| 項目 | REST + OpenAPI | GraphQL | tRPC |
|---|---|---|---|
| スキーマ定義 | 必要(YAML/JSON) | 必要(SDL) | 不要 |
| コード生成 | 必要 | 必要 | 不要 |
| 型安全性 | 生成後のみ | 生成後のみ | 常時 |
| ランタイムオーバーヘッド | なし | あり | 最小 |
| 学習コスト | 中 | 高 | 低 |
tRPC の最大の利点は、TypeScript のみで完結する点である。別言語のスキーマを学ぶ必要がなく、IDE の補完機能がそのまま活用できる。保存前に型エラーが検出されるため、APIの契約違反がデプロイ前に発見される。
Next.js との統合
tRPC は Next.js との親和性が高く、App Router でも Pages Router でも利用可能である。特に Next.js 15以降では、Server Actions との組み合わせで、よりシームレスなフルスタック開発が可能になっている。
T3 Stack(Next.js + tRPC + Prisma + Tailwind CSS)は、フルスタック TypeScript 開発のベストプラクティスとして広く採用されている。このスタックでは、データベースから UI まで一貫した型安全性が保証される。
// Prisma で定義した型が tRPC を経由して
// フロントエンドまで自動的に伝播する
const users = await trpc.user.list.query();
// users[0].createdAt の型が Date であることを
// TypeScript が自動的に認識
導入時の考慮事項
tRPC はフルスタック TypeScript 環境を前提としている。以下のケースでは、REST や GraphQL の方が適切な場合がある。
- マルチ言語クライアント:モバイルアプリ(Swift/Kotlin)など、TypeScript 以外のクライアントがある場合
- パブリック API:外部開発者向けに API を公開する場合は、OpenAPI 仕様の方が汎用性が高い
- マイクロサービス間通信:サービス間の通信では gRPC の方がパフォーマンスが高い場合がある
一方、BFF(Backend for Frontend)パターンや、チーム内で閉じたフルスタックアプリケーションでは、tRPC の生産性向上効果は絶大である。
FAQ
tRPC は本番環境で使用できますか?
はい、多くの企業で本番運用されている。Cal.com、Ping.gg など、大規模なプロダクトでも採用実績がある。
認証やミドルウェアはどう実装しますか?
tRPC はミドルウェア機能を提供しており、認証チェックやロギングをプロシージャに適用できる。コンテキストを通じて認証情報を各プロシージャに渡すパターンが一般的である。
REST API と併用できますか?
はい、既存の REST API と並行して tRPC を導入し、段階的に移行することが可能である。両方のエンドポイントを同じサーバーで提供できる。
バリデーションはどう行いますか?
Zod、Yup、Superstruct などのバリデーションライブラリと統合されている。.input() でスキーマを定義すると、ランタイムバリデーションと型推論が同時に行われる。
参考文献
- tRPC - Move Fast and Break Nothing — tRPC 公式サイト
- tRPC Documentation — tRPC 公式ドキュメント
- From REST to tRPC: Type-Safe APIs with Node.js — Better Stack Community
- Achieving End-to-End Type Safety in Full-Stack TypeScript with tRPC — Leapcell
- The 8 trends that will define web development in 2026 — LogRocket Blog



