Skip to main content
開発 モバイル

OpenAPI TypeScript: Generate Types, Clients,とValidation

マーティン・ドナディュー

通常、__CAPGO_KEEP_0__ pipeline がチームに嘘をつく瞬間を認識できます。スキーマが変更され、生成された型が更新され、問題なく、PR が緑色になり、そしてフロントエンドの誰かが古いレスポンスの形を読み続けているのに、ラッパーがエラーを無視しています。その時点が OpenAPI TypeScript の問題であり、ジェネレータがインターフェイスを吐くことの問題ではありません。

You can usually spot the moment an API pipeline starts lying to the team. A schema changes, the generated types update without complaints, the PR goes green, and then somebody in the front end keeps reading the old response shape because the wrapper cast the error away. That’s the OpenAPI TypeScript problem, not whether a generator can spit out interfaces.

OpenAPI TypeScript OpenAPI TypeScript pipeline の選択肢として、トレードオフがはるかに明確になり、ツールは全ての解決策であると装うのをやめます。

目次

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

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

生成された型の罠 TypeScriptは生成された型を消費するcodeを保護することができるが、ただし、トランスポート層が契約を再度消去しない限りOpenAPI側はスキーマを提供するだけであり、すべてのコールャーがそれを尊重する保証はしない。 理解するAPIの接続に関する議論 はここで役に立つように思われます。なぜなら、会話を単一のツールからシステムがつながる方法へと移すのに役立つからです。

失敗の場所はどこにあるか

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

ラッパーが嘘をつくことができる場合、ジェネレータはあなたを救うことができません。 __CAPGO_KEEP_0__

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

より広範な運用上の質問は、セキュリティと契約の規範、開発者にとっての便利さだけではなく、です。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 チームが生成された表面に enum を好む場合に重要です。 --enum プロジェクトのドキュメントは明確です。生成タイプのツールであり、クライアントランタイムやリクエストレイヤーではありません。軽量でタイプ優先のセットアップを実現するために、この制限は役立ちます。リポジトリも、ツールのメンテナンスモデルを示しています。これは、ドキュメントやリリースが活発に更新されているオープンソースツールが実用的なプロダクション環境で機能する理由の 1 つです。

オープンソースメンテナンスの利点についての議論です。 実践的な読み物です。__CAPGO_KEEP_0__ リポジトリと __CAPGO_KEEP_1__ ドキュメント Wire generation intoWire generation into GitHub repository and CLI documentation.

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

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

の使用を推奨している。

仕様を明示的に管理しないと、ジェネレータは不明性を元の状態に戻すことになる。

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

パターン ビルド時 出力ファイル バンドルサイズ 最適な選択
コンテキスト: Capgo Builder / ネイティブクラウドビルド製品ページ。役割: 短いUIラベルまたはナビゲーションアイテム。メッセージキー `native_build_builder_compare_fit_feature` (ネイティブビルドビルダー比較フィット機能)。 純粋なタイプのラッパー 高速
コントロールを求めるチームと小さな実行時サーフェイス 遅い 多くの 高い 迅速なハンドオフと自動生成された操作を求めるチーム
コード生成要求ビルダーなし 速い なしまたは最小限 1つのコードベースのアプリケーションが手書きのトランスポートロジックを好む

選択肢は実際には「どのツールが勝つか」ではなく、リポジトリ、チーム、APIが見る変化の量に合ったパイプラインの形がどれかです。2025年のベンチマークでは、大きなOpenAPI仕様約75,000行、2MB、約1,200操作について 約75,000行、2MB、約1,200操作のOpenAPI仕様について, 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を使用した薄いTypedクライアントのワイヤリング

生成されたTypeScriptAPI定義を使用してWebリクエストのTypedクライアントワッパプロセスを示す図。

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

なので

  • APIの型付きクライアントワッパは、APIの呼び出しを簡素化し、APIの呼び出しをより安全に実行することを目的としています。 APIの呼び出しを簡素化するためにAPIの型付きクライアントワッパを使用することで、APIの呼び出しをより安全に実行することができます。 /users/{id} __CAPGO_KEEP_0__ id.
  • クエリオブジェクトは型付きで残ります オプションのフィルタが文字列スープに変わりません。
  • レスポンスボディは型付きで残ります codeのパースは、期待する狭い形に信頼できます。

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

ラッパーを面白くしないで依存性を軽くしてください。将来のコードジェネレータの変更があれば、すべてのアプリに波及効果が生じます。

共通の失敗は、生成された型が古いラッパー署名と一致しない場合に、__CAPGO_KEEP_0__をパッチすることです。そうすると、緑のビルドが得られますが、アプリは脆弱になります。生成器が明らかにした契約違反も隠します。 as any Axiosを使用するチームの場合、パターンは同じですが、トランスポート実装が変更されます。より単純なブラウザ側の__CAPGO_KEEP_0__を望むチームの場合、

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, ajvは、境界チェックを処理します。コンパイル時型では実行できません。 io-ts 検証はデータがアプリケーションに入る場所で行われます。

Reactアプリケーションの場合、エッジは通常、要求が解決した直後で、ペイロードがステートに入る前にあります。サーバーの場合、ペイロードはデータベースに書き込まれる前に、またはビジネス ルールに渡される前にあります。ルールは単純です。検証は境界近くに近づけ、機能__CAPGO_KEEP_0__内に散らばる手動チェックを散らばらせないようにしてください。

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(),
});

は、サーバー上の高トラフィック JSON スキーマ検証を実現するために ajv は、生成されたレスポンスの形を反映する形を生成できます。 io-ts まだ、既存のチームに合う fp-ts 組み立て方のスタイル

大きな間違いは、検証が遅いことです。ペイロードがアプリに最初に到達すると、型システムはすでに回避されており、バグは隠れ場所を得ています。JavaScriptのユニットテストについての短いガイド はこの考え方とよく相性が良いです。ユニットテストと境界検証は、両方とも、悪い仮定を早く捕まえることが最も効果的です。 境界が明確なレイヤー

OpenAPI TypeScript 契約を生成し、検証者が実行時ペイロードをチェックし、アプリは__CAPGO_KEEP_0__にのみデータが両方のステップを通過したデータを表示します。静的型が不信頼されたレスポンスを監視するのではなく、契約が実行される方が良い境界です。 generates the contract, the validator checks the runtime payload, and your app code only sees data that survived both steps. That’s a much better boundary than trusting a static type to police an untrusted response.

https://__CAPGO_KEEP_0__.comからスクリーンショット

Screenshot from https://github.com

、__CAPGO_KEEP_0__の形状をモックまたは契約ツールでテストし、マージする前に実行します。生成器のバージョンを固定することで 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人のエンジニアでも意図しない結果を生まさないようにする。

A simple GitHub Actions shape

A practical workflow looks like this:

  1. リポジトリまたは生成されたソースから仕様をPullする。
  2. タイプを再生成する。
  3. 失敗するジョブは git diff 変更が表示される。
  4. 実行する。 tsc --noEmit.
  5. 契約テストを実行する。MockサーバーとしてPrismまたはSpectralバックアップされたチェックを使用する。

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

Mockサーバーは、バックエンドとフロントエンドの作業が時間やチームの境界によって隔てられている場合に特に役立ちます。Consumer code に予測可能な API サーフェイスを提供しながら、実際の契約ではなく固定されたフィクスチャではなく契約をチェックすることができます。 継続的インテグレーション設定ガイド は、チームがまだクリーンで繰り返し可能なCI基準を必要としている場合の便利なリファレンスです。

ジェネレータのバージョンを固定することで、コードジェネレーションパイプラインのいちばんひどい失敗を回避できます。ジェネレータをローカルにアップグレードした開発者と、アップグレードしなかった開発者の間で、生成されたファイルがランダムなノイズになるのを防ぐことができます。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.

あなたが Capacitor または Electron アプリを配信している場合、更新パイプラインが同じ規律で動作するようにしたい場合は、 Capgo は、JavaScript、CSS、コピー、設定、資産の修正を迅速に実行できる実用的な方法を提供します。Visit Capgo 更新パイプラインの速度と制御を両立させるために、署名バンドル、ロールバック保護、リリース制御を含むリリースプロセスを確認してみましょう。

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

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

マーティンによる人間のサポート

スタートする

最新のブログ記事

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