メインコンテンツへスキップ
バージョン: 11.x

OpenAPI (アルファ版)

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

注意

このパッケージはアルファ版です。APIは予告なく変更される可能性があります。

@trpc/openapiパッケージは、tRPCルーターからOpenAPI 3.1仕様を生成します。生成された仕様を使って次のことが可能です:

  • 任意の言語で型安全なAPIクライアントを生成する

  • PostmanやInsomniaなどのHTTPツールでtRPCエンドポイントを呼び出す

  • MCPサーバーなどのAIエージェント連携を有効化する

インストール

bash
pnpm add @trpc/openapi
bash
pnpm add @trpc/openapi
AIエージェント

AIコーディングエージェントを使用している場合は、コード生成の品質向上のためにtRPCスキルをインストールしてください:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install
注記

@trpc/openapiの現在のバージョン形式は11.x.x-alphaです。最新のtRPC v11バージョンで動作しますが、通常通りバージョン番号を揃えることを推奨します

tRPC設定の調整

既存のルーターをそのまま利用可能で、アノテーションやデコレーターは不要です。注意点を以下に示します:

  • 出力型の不要性 — 他のOpenAPIツールとは異なり、.output()スキーマはオプションです。生成ツールは実装から戻り型を自動推論します。

  • トランスフォーマー — サーバーでデータトランスフォーマーを使用する場合、OpenAPIクライアントも同じものを使用する必要があります。設定方法や他言語対応はトランスフォーマーを参照してください。

  • サブスクリプション — 現在は生成仕様から除外されています。SSEサポートを予定しています。

  • 説明文 — Zodの.describe()呼び出しや、型・ルーター・プロシージャのJSDocコメントは、仕様内のdescriptionフィールドに変換されます。

仕様の生成

CLI

bash
pnpm exec trpc-openapi ./src/server/router.ts
bash
pnpm exec trpc-openapi ./src/server/router.ts
OptionDefaultDescription
-e, --export <name>AppRouterName of the exported router type
-o, --output <file>openapi.jsonOutput file path
--title <text>tRPC APIOpenAPI info.title
--version <ver>0.0.0OpenAPI info.version
bash
pnpm exec trpc-openapi ./src/server/router.ts -o api.json --title "My API" --version 1.0.0
bash
pnpm exec trpc-openapi ./src/server/router.ts -o api.json --title "My API" --version 1.0.0

プログラム的生成

scripts/generate-openapi.ts
ts
import { generateOpenAPIDocument } from '@trpc/openapi';
const doc = generateOpenAPIDocument('./src/server/router.ts', {
exportName: 'AppRouter',
title: 'My API',
version: '1.0.0',
});
scripts/generate-openapi.ts
ts
import { generateOpenAPIDocument } from '@trpc/openapi';
const doc = generateOpenAPIDocument('./src/server/router.ts', {
exportName: 'AppRouter',
title: 'My API',
version: '1.0.0',
});

生成ツールはルーターのTypeScript型を静的に解析します — コードを実行することはありません。

仕様からクライアントを生成

どのOpenAPIクライアント生成ツールでも動作しますが、最もテスト済みの統合はHey APIです。

生成されたクライアントは、tRPCプロシージャに対応する型付きSDK関数を提供します:

  • クエリGET /procedure.path

  • ミューテーションPOST /procedure.path

  • サブスクリプションは無視されます(SSE対応予定)

Hey API (TypeScript)

Hey API ドキュメント

bash
pnpm add @trpc/openapi @hey-api/openapi-ts
bash
pnpm add @trpc/openapi @hey-api/openapi-ts

標準では、OpenAPI生成クライアントはトランスフォーマー設定やクエリパラメータのエンコード方法を認識しません。@trpc/openapi/heyapiパッケージが提供するconfigureTRPCHeyApiClientヘルパーがこのギャップを埋めます — リクエストのシリアライズ、レスポンスのパース、エラーのデシリアライズを設定し、生成されたSDKがtRPCエンドポイントで正しく動作するようにします。

トランスフォーマー未使用の場合

この場合はHey APIのCLIまたはプログラム的APIを使ってクライアントを生成できます

bash
pnpm exec openapi-ts -i openapi.json -o ./generated
bash
pnpm exec openapi-ts -i openapi.json -o ./generated

次に、ランタイムで少しの設定が必要です:

src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { Sdk } from './generated/sdk.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
});
const sdk = new Sdk({ client });
const result = await sdk.greeting({ query: { input: { name: 'World' } } });
const user = await sdk.user.create({ body: { name: 'Bob', age: 30 } });
src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { Sdk } from './generated/sdk.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
});
const sdk = new Sdk({ client });
const result = await sdk.greeting({ query: { input: { name: 'World' } } });
const user = await sdk.user.create({ body: { name: 'Bob', age: 30 } });

トランスフォーマー使用時 (superjson, devalueなど)

警告

バックエンドがsuperjsonのようなデータトランスフォーマーを使用する場合、クライアント設定に同じものを渡す必要があります。これを行わないと、Date、Map、Setなどの非JSON型が暗黙的に誤った値になる可能性があります。

まずHey APIのプログラム的APIを使ってクライアントコードを生成します。これによりcreateTRPCHeyApiTypeResolversを使用して、出力される型が正しいことを保証できます:

src/client.ts
ts
import { createClient } from '@hey-api/openapi-ts';
import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';
const openApiJson = './path/to/openapi.json'
const outputDir = './generated'
await createClient({
input: openApiJson,
output: outputDir,
plugins: [
{
name: '@hey-api/typescript',
// Important: this ensures that your emitted types like Dates are correct
'~resolvers': createTRPCHeyApiTypeResolvers(),
},
{
name: '@hey-api/sdk',
operations: { strategy: 'single' },
},
],
});
src/client.ts
ts
import { createClient } from '@hey-api/openapi-ts';
import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';
const openApiJson = './path/to/openapi.json'
const outputDir = './generated'
await createClient({
input: openApiJson,
output: outputDir,
plugins: [
{
name: '@hey-api/typescript',
// Important: this ensures that your emitted types like Dates are correct
'~resolvers': createTRPCHeyApiTypeResolvers(),
},
{
name: '@hey-api/sdk',
operations: { strategy: 'single' },
},
],
});

ランタイムで生成クライアントをトランスフォーマーと共に設定すると、ネイティブ型を直接渡せ、デシリアライズされた状態で取得できます:

src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
// Important, this transformer must match your tRPC API's transformer:
transformer: superjson,
});
const sdk = new Sdk({ client });
const event = await sdk.getEvent({
query: { input: { id: 'evt_1', at: new Date('2025-06-15T10:00:00Z') } },
});
// event.data.result.data.at is a Date object ✅
const created = await sdk.createEvent({
body: { name: 'Conference', at: new Date('2025-09-01T09:00:00Z') },
});
src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
// Important, this transformer must match your tRPC API's transformer:
transformer: superjson,
});
const sdk = new Sdk({ client });
const event = await sdk.getEvent({
query: { input: { id: 'evt_1', at: new Date('2025-06-15T10:00:00Z') } },
});
// event.data.result.data.at is a Date object ✅
const created = await sdk.createEvent({
body: { name: 'Conference', at: new Date('2025-09-01T09:00:00Z') },
});

別の生成ツールや言語を使用する場合

生成されたOpenAPI仕様は、以下の機能を持つ任意のOpenAPI互換クライアントジェネレータで動作します:

  • Dateなどのクラスに対する正確な型生成

  • 検索パラメータやリクエスト/レスポンスボディのシリアライゼーションカスタマイズのサポート

tRPCのプロトコルと正しく連携するためには、生成されたクライアントで以下の2点を設定する必要があります:

  • トランスフォーマー — tRPC APIがトランスフォーマーを使用している場合、クライアントは同じフォーマットで入力をシリアライズし、出力をデシリアライズする必要があります

  • クエリ入力 — GETリクエストでは、入力は個別のクエリパラメータではなく ?input=<JSON> としてエンコードされます

完全なリファレンス実装については Hey API設定ソース を参照してください。

トランスフォーマー

tRPCのデータトランスフォーマーを使用すると、DateMapSetBigInt などのリッチな型を通信経路で送信できます。OpenAPIクライアントを使用する場合、入力が正しくシリアライズされ、出力が正しくデシリアライズされるように、サーバーとクライアントの両方で同じトランスフォーマーを設定する必要があります。

tRPCの DataTransformer インターフェイス (serialize / deserialize) を実装する任意のトランスフォーマーは configureTRPCHeyApiClient で動作します。以下はテスト済みのオプションです。

SuperJSON

TypeScript-to-TypeScript環境で最も人気のあるトランスフォーマーです。DateMapSetBigIntRegExp などを処理します。

bash
pnpm add superjson
bash
pnpm add superjson
src/server.ts
ts
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';
const t = initTRPC.create({ transformer: superjson });
src/server.ts
ts
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';
const t = initTRPC.create({ transformer: superjson });
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: superjson,
});
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: superjson,
});

完全なエンドツーエンドの例については superjsonテスト を参照してください。

MongoDB Extended JSON v2

EJSON はクロスランゲージサポートが必要な場合に適した選択肢です。bson npmパッケージは EJSON.serialize / EJSON.deserialize を提供し、これらは直接tRPCの DataTransformer にマッピングされます。

対応言語: C, C#, C++, Go, Java, Node.js, Perl, PHP, Python, Ruby, Scala

bash
pnpm add bson
bash
pnpm add bson
src/transformer.ts
ts
import { EJSON } from 'bson';
import type { TRPCDataTransformer } from '@trpc/server';
export const ejsonTransformer: TRPCDataTransformer = {
serialize: (value) => EJSON.serialize(value),
deserialize: (value) => EJSON.deserialize(value as Document),
};
src/transformer.ts
ts
import { EJSON } from 'bson';
import type { TRPCDataTransformer } from '@trpc/server';
export const ejsonTransformer: TRPCDataTransformer = {
serialize: (value) => EJSON.serialize(value),
deserialize: (value) => EJSON.deserialize(value as Document),
};
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { ejsonTransformer } from './transformer';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: ejsonTransformer,
});
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { ejsonTransformer } from './transformer';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: ejsonTransformer,
});

完全なエンドツーエンドの例については MongoDB EJSONテスト を参照してください。

Amazon Ion

Amazon Ion は豊富な型システムを持つデータフォーマットで、幅広い言語サポートを提供します。TRPCDataTransformer インターフェイスを直接サポートせず、JS/TSでtRPCと連携させるにはボイラープレートコードが必要ですが、独自システムでは有効な選択肢となり得ます。

対応言語: C, C#, D, Go, Java, JavaScript, PHP, Python, Rust

bash
pnpm add ion-js
bash
pnpm add ion-js

トランスフォーマーの実装、ボイラープレート、完全なエンドツーエンドの例については Amazon Ionテスト を参照してください。

カスタムトランスフォーマーの作成

serialize メソッドと deserialize メソッドを持つ任意のオブジェクトが機能します:

ts
import type { TRPCDataTransformer } from '@trpc/server';
const myTransformer: TRPCDataTransformer = {
serialize: (value) => {
/* encode rich types */
},
deserialize: (value) => {
/* decode them back */
},
};
ts
import type { TRPCDataTransformer } from '@trpc/server';
const myTransformer: TRPCDataTransformer = {
serialize: (value) => {
/* encode rich types */
},
deserialize: (value) => {
/* decode them back */
},
};

サーバー側では initTRPC.create({ transformer }) に、クライアント側では configureTRPCHeyApiClient(client, { transformer }) に渡します。詳細は データトランスフォーマードキュメント を参照してください。

完全な例

すべてのステップを統合した完全な実行可能プロジェクトについては openapi-codegenサンプル を参照してください。