openapi-fetchは、あなたのOpenAPIスキーマを取り込み、型安全なfetchクライアントを提供します。このライブラリはわずか 6 kb で、ほとんどのランタイムを持たず、React、Vue、Svelte、あるいはバニラJSとも動作します。
ライブラリ | サイズ (min) | “GET” リクエスト* |
---|---|---|
openapi-fetch | 6 kB | 300k ops/s (最速) |
openapi-typescript-fetch | 3 kB | 300k ops/s (最速) |
feature-fetch | 15 kB | 300k ops/s (最速) |
axios | 32 kB | 225k ops/s (1.3倍遅い) |
superagent | 55 kB | 50k ops/s (6倍遅い) |
openapi-typescript-codegen | 367 kB | 100k ops/s (3倍遅い) |
* ベンチマークはおおよそのものです 。実際のパフォーマンスはマシンやブラウザによって異なる場合があります。ライブラリ間の相対的なパフォーマンスはより信頼性があります。
このシンタックスは、React QueryやApollo Clientのような人気のライブラリにインスパイアされたものでありながら、すべての装飾を省き、6 kbというコンパクトなパッケージに収まっています。
import createClient from "openapi-fetch";
import type { paths } from "./my-openapi-3-schema"; // openapi-typescriptで生成された型
const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });
const {
data, // 2XXレスポンスの場合のみ存在
error, // 4XXまたは5XXレスポンスの場合のみ存在
} = await client.GET("/blogposts/{post_id}", {
params: {
path: { post_id: "123" },
},
});
await client.PUT("/blogposts", {
body: {
title: "新しい投稿",
},
});
data
と error
は型チェックが行われ、VS Code や他の TypeScript 対応 IDE で Intellisense による補完が利用可能です。同様に、リクエストの body
もフィールドが型チェックされ、必要なパラメータが不足している場合や型の不一致がある場合にはエラーが発生します。
GET()
, PUT()
, POST()
などは、ネイティブの fetch API の薄いラッパーとして動作します(任意の呼び出しに変更することも可能です)。
ここで重要なのは、ジェネリクスや手動の型指定が一切不要で、エンドポイントのリクエストとレスポンスが自動的に推論されることです。これは、エンドポイントの型安全性を大幅に向上させます。なぜなら、手動でのアサーションはバグの原因となり得るからです!これにより、次のような問題がすべて解消されます:
- ✅ URLやパラメータのタイプミスが起こらない
- ✅ すべてのパラメータ、リクエストボディ、レスポンスが型チェックされ、スキーマと100%一致する
- ✅ APIの手動での型指定が不要
- ✅ バグを隠す可能性がある
any
型の排除 - ✅ バグを隠す可能性がある
as
による型の上書きも排除 - ✅ これらすべてが6 kbのクライアントパッケージで実現 🎉
セットアップ
このライブラリと openapi-typescript をインストールします:
npm i openapi-fetch
npm i -D openapi-typescript typescript
強く推奨
tsconfig.json
で noUncheckedIndexedAccess を有効にしてください (ドキュメント)
次に、openapi-typescriptを使用してOpenAPIスキーマからTypeScriptの型を生成します:
npx openapi-typescript ./path/to/api/v1.yaml -o ./src/lib/api/v1.d.ts
最後に、プロジェクトで 型チェックを実行 してください。これは、tsc --noEmit
を npm scripts に追加することで可能です:
{
"scripts": {
"test:ts": "tsc --noEmit"
}
}
そして、CIで npm run test:ts
を実行して型エラーを検出します。
TIP
tsc --noEmit
を使用して型エラーをチェックし、リンターやビルドコマンドに依存しないようにしてください。TypeScriptコンパイラ自体ほど正確に型チェックを行えるものはありません。
基本的な使用方法
openapi-fetchを従来のコード生成ツールよりも使用する最大の利点は、ドキュメントが不要であることです。openapi-fetchは、どの関数をインポートするか、あるいはその関数がどのパラメータを受け取るかを探す代わりに、既存のOpenAPIドキュメントを活用することを推奨しています:
import createClient from "openapi-fetch";
import type { paths } from "./my-openapi-3-schema"; // openapi-typescriptで生成された型
const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });
const { data, error } = await client.GET("/blogposts/{post_id}", {
params: {
path: { post_id: "my-post" },
query: { version: 2 },
},
});
const { data, error } = await client.PUT("/blogposts", {
body: {
title: "New Post",
body: "<p>New post body</p>",
publish_date: new Date("2023-03-01T12:00:00Z").getTime(),
},
});
- HTTPメソッドを
createClient()
から直接取得します。 GET()
,PUT()
などに希望するpath
を渡します。- TypeScriptが欠落しているものや無効なものがあれば有用なエラーを返します。
Pathname
GET()
, PUT()
, POST()
などのpathnameは、スキーマと厳密に一致している必要があります。例では、URLは /blogposts/{post_id}
です。このライブラリは、すべての path
パラメータをすぐに置き換え、それらが型チェックされるようにします。
TIP
openapi-fetch は URL から型を推論します。動的な実行時の値よりも静的な文字列値を優先してください。例:
- ✅
"/blogposts/{post_id}"
- ❌
[...pathParts].join("/") + "{post_id}"
このライブラリはまた、label および matrix のシリアライゼーションスタイルもサポートしています(ドキュメント)。
Request
GET()
リクエストには、タイプごとにパラメータをグループ化する params
オブジェクトが必要です( path
または query
)。必須のパラメータが欠けている場合や、型が間違っている場合には、型エラーが発生します。
POST()
リクエストでは、必要な requestBody データを提供する body
オブジェクトが必要でした。
Response
すべてのメソッドはdata、errorおよび responseを持つオブジェクトを返します。
const { data, error, response } = await client.GET("/url");
Object | Response |
---|---|
data | OKの場合 2xx レスポンス、そうでない場合 undefined |
error | OKでない場合 5xx 、4xx 、または default レスポンス、それ以外は undefined |
response | オリジナルのレスポンスであり、status , headers などを含みます。 |
Path-property スタイル
パスをプロパティとして選択する方が好ましい場合は、パスベースのクライアントを作成できます:
import { createPathBasedClient } from "openapi-fetch";
import type { paths } from "./my-openapi-3-schema"; // openapi-typescriptで生成された型
const client = createPathBasedClient<paths>({
baseUrl: "https://myapi.dev/v1",
});
client["/blogposts/{post_id}"].GET({
params: { post_id: "my-post" },
query: { version: 2 },
});
これにはパフォーマンスの影響があり、ミドルウェアを直接付与することはできません。 詳細については、wrapAsPathBasedClient
を参照してください。
サポート
プラットフォーム | サポート |
---|---|
ブラウザ | fetch API サポートを参照 (主要なブラウザで広く利用可能) |
Node | >= 18.0.0 |
TypeScript | >= 4.7 (>= 5.0 recommended) |