Skip to main content
開発 モバイル

OpenAPI TypeScript: 型、クライアント、検証の生成

OpenAPI TypeScript の生成方法を端から端まで学びましょう。型を生成し、クライアントを接続し、実行時で検証し、CI から安全に配布してください。

マーティン・ドナディエ

マーティン・ドナディエ

コンテンツマーケター

OpenAPI TypeScript: 型、クライアント、検証の生成

通常、API Pipelines がチームに嘘をつく瞬間を認識できます。スキーマが変更され、生成された型は苦情を言わずに更新され、PR が緑色になり、そして誰かがフロントエンドで古いレスポンスの形を読み続けているのです。そうでなければ、エラーをキャストして隠すラッパーが原因です。そうでなければ、OpenAPI TypeScript の問題ではありません。生成器がインターフェイスを吐き出すことのできるかどうかということではありません。

より有益な質問は、より難しいものです。スキーマ、トランスポート、検証の間の契約を何でしたか、どの部分がビルド時で失敗するべきか、どの部分が実行時で漏れ込むべきかを決定することです。そうすることで OpenAPI TypeScript pipeline としての選択肢、トレードオフがはっきりし、ツールが全ての解決策であると装うのをやめます。

目次

生成された型は安全なAPIと同じではない

チームメイトがオプショナルなレスポンスフィールドを追加するPRをマージする。生成されたファイルはきれいに更新され、diffは面白くないので、みんな進んで行く。するとフロントエンドは「一時的に」castされた手書きのラッパーを通して古い形状を読み続け、生産は契約が変更されたことのように振る始まる。 as any生成された型の罠

TypeScriptは生成された型を消費する__CAPGO_KEEP_0__を保護することができるが、ただし、トランスポート層が契約を再度消去しない限り code接続の理解に関する議論__CAPGO_KEEP_0__接続の理解 API システムの接続方法についての議論を、単一のツールから切り離すのに役立ちます。

失敗の場所

一般的なブレークポイントは、珍しいものではなく、単調なものです。 スキーマのずれ OpenAPIの仕様と実際に展開されたサービスが一致しなくなったときに発生します。 部分的なカバレッジ 仕様は正常なパスのみをモデル化しているのに対し、実際のアプリケーションは未記載のエッジケースに依存している場合に発生します。 手書きのラッパー 型が弱まることがよくあります。特に、誰かが「速く進む」ために使用した場合や、または緩いレスポンスのキャストを使用した場合です。 any 実用的なルール:

ラッパーが嘘をつくことができる場合、ジェネレータはあなたを救うことができません。 if the wrapper can lie, the generator can’t save you.

TypeScriptのランタイムでは、コンパイル後の型が失われ、不正なJSONがネットワークから流れてきた場合に拒否できません。エディターが推測したものはネットワークには関係ありません。したがって、生成されたクライアントは、より安全なAPI_PIPELINEの1層に過ぎません。

より広い運用上の質問は、セキュリティと契約の規範、開発者にとっての便利さだけではありません。API契約がより大きなアプリケーションライフサイクルにどのように整合するかを、構造化された視点で見るには、この内部ガイド APIアプリストアへの適合性のためのセキュリティスタンダード は、有用な相談相手です。

オープンAPIのTypeScriptの考え方は、次のとおりです。厳密なスキーマから型の橋渡しを提供することは素晴らしいですが、要求を検証せず、実行時パイロットの形状を強制せず、粗末なラッパーが全てを破壊するのを防ぐことはできません。ジェネレータは簡単な20%ですが、パイプラインの設計が残りで、チームは信頼を得るか、誤った自信を蓄積するかで決まります。 オープンAPIからTypeScriptの型を生成する https://openapi-ts.devからスクリーンショット

最も軽い有効なセットアップは、実際のリポジトリの変化に耐えられることが多いです。オープンAPIの仕様を同じリポジトリに保ち、コミットされた型ファイルを生成し、CIでドリフトを可視化するのではなく、リフレッシュステップを誰かが思い出すのではなくします。コマンド

は、レビューアが他のソース変更と同様に検査できる、決定的な出力ファイルを提供します。

実際に重要なフラグ npx openapi-typescript ./openapi.yaml -o ./src/types/api.d.ts __CAPGO_KEEP_0__は削除されました

__CAPGO_KEEP_0__は削除されました

The -o 出力フラグは、生成されたアーティファクトを明示的に生成するため、重要です。 --immutable 生成されたタイプを出力に readonly の意図を保持し、スキーマの順序が意味のない変更で安定した diff を維持するために便利です。 --alphabetize 生成された表面に代わりに union を使用するチームがいる場合、生成されたタイプを出力に readonly の意図を保持するために重要です。 --enum 出力フラグは、生成された表面に代わりに enum を使用するチームがいる場合に重要です。

プロジェクトのドキュメントは、スコープが明確であることを明確に述べています。生成されたタイプのジェネレータであり、クライアントランタイムやリクエストレイヤーではありません。軽量でタイプ優先のセットアップを実現するために、この制限は役立ちます。 ジェネレータリポジトリも、ツールのメンテナンスモデルを示しています。これは、ドキュメントやリリースが活発に更新されている場合に、オープンソースツールが実際に生産環境で機能する理由です。 オープンソースメンテナンスのケース実践的な読み物は、プロジェクトの GitHub repository and CLI documentation.

__CAPGO_KEEP_1__ package.json コマンドはビルドスクリプトの隣に置かれ、スピスの変更ごとに実行する。CIではファイルを再生成し、ドリフトが表示される場合は失敗する。 git diff ドリフトが表示されることは、契約の変更が可視化されたレビュー作業になるのではなく、静的な実行時リスクになるのではなくなる。

スキーマ側もコマンドラインと同じくらい重要である。プロジェクトでは compilerOptions.noUncheckedIndexedAccess の使用を推奨している。 additionalProperties の使用を推奨している。 T | undefinedの使用を推奨している。 oneOf の使用を推奨している。 $defs の使用を推奨している。 openapi-typescript の使用を推奨している。 anyの使用を推奨している。

の使用を推奨している。

の使用を推奨している。

Pure Types、フルクライアント、コードジェネレータの選択

パターン ビルド時 出力ファイル バンドルサイズ 最適
純粋なタイプとスリムラッパー 高速 コントロールと小さな実行時サーフェイスを望むチーム
フルクライアントコードジェネレータ 遅い 多くの 高い チームが迅速なハンドオフと自動生成された操作を望む
コード生成要求ビルダーなし 速い なしまたは最小限 単一コードベースのアプリケーションが手書きのトランスポートロジックを好む

選択肢は実際には「どのツールが勝つか」ということではありません。APIが見る中断の量、リポジトリ、チーム、パイプラインの形に合うものを選ぶことです。2025年のベンチマークでは、約75,000行、2MB、約1,200操作の大きいOpenAPI仕様について 約75,000行、2MB、約1,200操作, openapi-typescript1.5秒 平均で約 8.0秒 に対して @hey-api/openapi-ts, 5.5秒 に対して Orval, そして 18.1秒 に対して Kubb, また1つの出力ファイルを生成する 16 に対して hey-api, 2,719 に対して Orval、そして 3,877Kubb (ベンチマークの詳細).

純粋な型は制御を優先します

純粋な型の設定は、手書きの要求レイヤーと組み合わせると、実行時間を小さくし、APIの表面を面白くすることができます。 これは、バンドラーに敏感なフロントエンドと、スピックとコンシューマーを同じチームが所有するアプリケーションで重要です。 開発者体験が単にシンタックスシュガーではないことを思い出させる必要がある場合は、 開発者体験の角度 は、クライアントcodeが短く明確でレビュー可能な場合に判断しやすくなります。

フルクライアントはハンドオフのスピードを優先します

openapi-generator, hey-api, Orval、そして Kubb すべては、タイプよりも多くのことを行うことを試みています。 これは、要求メソッド、モデル、パイプラインを一緒に生成したい場合に役立ちます。 例えば、バックエンドとフロントエンドのチーム間で大きなハンドオフがある場合。 そのコストは、ベンチマーク上で明らかです。 生成されたファイルが多く、実行時間の表面が大きく、スピックの拡大とともにビルドの摩擦が増すことです。

コードジェネレーションをせずにローカルに修正する

型付きの要求ビルダーと fetch wrapperは、両端の形状を所有するコードベースが一つで、APIの変更が密接に調整されている場合にうまく機能します。欠点は、メンテナンスの Disciplineです。生産者と消費者の間のチームとリポジトリが増えると、手動で要求層を維持することのリスクが高まります。強力な契約テストを強制することによって除くことができます。

コアの決定点は、イデオロギー的なものではありません。バンドル予算が限られている場合、純粋な型は魅力的です。チームが最大限のサボテージングを望み、出力を吸収できる場合、フルクライアントはセットアップ時間を短縮できます。契約を近く保つことができ、最小限の動作部品が必要な場合、ノーコードジェン request ビルダが適切な内部取引になります。

FetchまたはAxiosを囲むThin Typed Clientのワイヤリング

生成されたTypeScript API定義を使用してWeb要求のプロセスを示す図。

Thin wrapperは、ジェネレータが止まり、Application codeが始まる場所です。ラッパーは、1つの関数を1つの操作につき、型付きパラメータとクエリオブジェクトを受け取り、呼び出しを fetch またはインジェクションされた axios インスタンスに転送することなく、賢くないことを試みないでください。ほとんどの生産環境では、その層は 30–60行 生成された型が形状のほとんどを含んでいるためです。

ここに、持続するメンタルモデルがあります:

  • パスパラメータは型付きで残ります なので /users/{id} API呼び出しを行うには__CAPGO_KEEP_0__が必要です。 id.
  • クエリオブジェクトは型付きで残ります。 つまり、オプションフィルタが文字列スープに変わりません。
  • レスポンスボディは型付きで残ります。 したがって、codeをパースする際は、期待する狭い形状に信頼できます。

そのようなラッパーは意図的に面白くありません。リトライ、変換、または認証ポリシーを発明するべきではありません。そうするべきではありません。型付きの操作からリクエストを移動し、型付きの結果を上に返すだけです。

ラッパーを面白くしないで依存性を軽減するか、または将来のコードジェネレータの変更があれば、すべてのアプリに影響を与えることになる。

共通の失敗は、生成された型が古いラッパー署名と一致しない場合にパッチを当てることです。 as any これは、緑のビルドと脆弱なアプリを買う代わりに、生成器が明らかにした契約違反を隠します。

For teams that prefer Axios, the pattern is the same, only the transport implementation changes. For teams that want simpler browser-side code, fetch よりシンプルなブラウザ側の__CAPGO_KEEP_0__が必要なチームの場合、よくあることです。

重要なのは、リクエスト関数が生成されたパス型を受け取り、型付きのレスポンスを返すこと、または後でマッサージする必要がある、ゆるい形状のオブジェクトを返さないことです。 openapi typescript gives you a clean division of labor. Schema lives in the spec, transport lives in the wrapper, and the app sees typed operations instead of ad hoc request code.

zod、ajv、またはio-tsを使用したランタイム検証の追加

TypeScriptの型は実行時には消え、ネットワークはエディターの信頼性を気にしません。そのため、安全なパターンは「型を生成し、希望する」ではなく、「型を生成し、エッジで不信頼できるデータがアプリケーションに入る場所で検証する」です。生成されたスキーマは真実の源であり、検証ライブラリ zod, ajvio-ts は、コンパイル時型が実行できない境界チェックを処理します。

データが入る場所で検証する

For React apps, the edge is usually right after the request resolves and before the payload enters state. For servers, it’s before the payload is written into a database or handed to a business rule. The rule is simple, keep validation close to the boundary and don’t scatter manual checks through feature code.

の間で散らばった手動チェックを散らばさないようにします。 zod は、生成されたレスポンスの形を反映する形を生成できますが、置き換えることはありません:

import { z } from "zod";

const WeatherForecastSchema = z.object({
  date: z.string(),
  temperatureC: z.number(),
  summary: z.string().nullable(),
  temperatureF: z.number().optional(),
});

この例では、スキーマがオプショナルフィールドをマークしたフィールドを検証し、実行時チェックを生成したものと同期しています。 ajv は、高スループットのJSONスキーマ検証をサーバー側で実行する際に強力な選択肢です。 io-ts まだ、既存のチームに合う。 fp-ts 組み立て方のスタイル。

大きな間違いは、データがアプリ内に到達する前に検証しないことです。データがアプリ内に到達すると、型システムはすでに回避され、バグは隠れ場所を得ます。JavaScriptのユニットテストについての短いガイドは、この考え方とよく相性が良いです。ユニットテストと境界検証は、両方とも、悪い仮定を早い段階でキャッチすることが最も効果的です。 境界検証は予測可能です。 OpenAPI TypeScript

契約を生成し、検証者が実行時データをチェックし、アプリは__CAPGO_KEEP_0__にのみデータが両方のステップを通過したデータを表示します。静的型が不信頼できるレスポンスを監視するのではなく、契約を信頼する方がはるかに良い境界です。 生成、検証、契約テストをCIに組み込む https://code.comからスクリーンショット

パイプラインが長く続くと、契約はゲートではなく、提案ではなくなる。型を再生成し、ドリフトで失敗し、統合前に__CAPGO_KEEP_0__の形状をモックまたは契約ツールで実行し、メインブランチにマージする前に実行する。生成器のバージョンを固定すると、

Screenshot from https://github.com

CIで実行する tsc --noEmit, and exercise the API shape against a mock or contract tool before merge. If you pin the generator version in package.json, 2 のエンジニアが同じ仕様から異なる出力を意図せずに生み出さないようにする。

単純な GitHub Actions 形式

実用的なワークフローは次のようになります。

  1. リポジトリまたは生成されたソースから仕様をPullします。
  2. 型を再生成します。
  3. もし git diff 変更が表示される場合。
  4. Run tsc --noEmit.
  5. PrismまたはSpectralバックアップされたチェックを備えたモックサーバーに対して契約テストを実行します。

契約テストとスナップショットテストの主な違いはスコープです。スナップショットはファイルが変更されたことを教えてくれますが、契約テストは仕様が何を言っているかを示します。

A mock server is especially useful when backend and frontend work are separated by time or team boundaries. It gives consumer code a predictable API surface while still checking the actual contract rather than a hard-coded fixture. The 継続的インテグレーション設定ガイド は、チームがクリーンで繰り返し可能なCI基準を必要としている場合に役立つ参考資料です。

生成器のバージョンを固定することで、コードジェネレータのパイプラインにおける最もひどい失敗の 1 つである、不可視の出力偏差を回避できます。開発者がローカルで生成器をアップグレードした場合、もう一人の開発者がアップグレードしなかった場合、生成されたファイルはランダムなノイズではなく信号になります。CI はそのようなことは不可能にすべきです。

結果として得られるパイプラインでは、スキーマの変更、型生成、コンパイラのチェック、契約テストがすべて相互に強化されます。それがワークフローの正直さを生み出します。

メンテナブルなパイプライン、パフォーマンス、最終チェックリスト

ソフトウェア開発プロジェクト用のOpenAPI TypeScriptパイプラインを維持するための4つの重要なステップを示すチェックリスト。

生存するパイプラインは、ものごとの管理が面白くないものだけです。仕様のバージョンを固定し、スキーマの変更を code のようにレビューし、生成器を固定し、破壊的な変更が承認される方法をドキュメント化してください。プロセスが曖昧な場合、人々はそれを回避し、生成された型は強制ではなく装飾になります。

実際に重要なパフォーマンスの調整器は数個あります。

モノレポジトリでは、仕様が頻繁に変更されるが、しかもそれを使用するのは1つのパッケージだけの場合、インクリメンタルな生成が役立ちます。 tsc --incremental コンパイラの作業を繰り返し削減し、実行時ビルドでは不要な出力フラグを無効にすることで、生成された表面を小さくできます。実際の最大の利点は、予測可能なパイプラインが頻繁に実行されるため、社会的な利点が技術的な利点よりも大きくなります。

以下のチェックリストは、最も価値のあるものです。

  • バージョン固定: ロックする openapi-typescript バージョン package.json したがって、出力はマシン間で漂うことはありません。
  • スキーマのレビュー: 仕様の変更を契約変更として扱い、メンテナンス作業として扱わないようにします。
  • 漂流検出: CIで再生成し、差分で失敗します。
  • エッジ検証: 不信頼性の高いペイロードをアプリケーション状態または永続化に到達する前にパースします。
  • 契約テスト: モックバックされたチェックを実行して、消費者codeがスキーマと一致していることを証明します。
  • 破壊的変更ポリシー: 形状の変更を承認する人と、クライアントが通知される方法を書き留めます。

A pipeline that includes those gates doesn’t just generate types, it makes the contract visible. That visibility is what keeps teams from trusting a file that only looks safe.

If you’re shipping Capacitor or Electron apps and you want your update pipeline to behave with the same discipline, Capgo gives you a practical way to move JavaScript, CSS, copy, config, and asset fixes quickly without waiting on app store review. Visit Capgo to see how its signed bundles, rollback protection, and release controls fit into a release process that needs speed without losing control.

Capacitor アプリ向けのリアルタイム更新

ウェブ層のバグが生じた場合、Capgo を通じて修正を配信し、数日間待つ必要のないアプリストアの承認を待つ必要がなくなる。ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路を通じて進む。

マーティンによる人工知能サポート

スタートする

最新のブログ記事

Capgo は、プロフェッショナルなモバイルアプリを作成するために必要な最良の洞察を提供します。