はじめに
正直なところ、バックエンドとフロントエンドの連携って地味に面倒なんですよね。
APIの型定義を手動で書いて、エンドポイントごとにfetch処理を書いて...そしてバックエンドの仕様が変わるたびに手動で修正。30代になって思うのは、この手の作業は自動化するに限るということ。
そんな悩みを解決してくれるのがHey APIというツールです。
Hey APIは、OpenAPI(Swagger)の仕様書からTypeScriptの型定義とAPIクライアントを自動生成してくれるコード生成ツール。GitHubで3,700スター以上、月間310万ダウンロードを超える実力派で、Google、Amazon、PayPalなどの大手企業でも採用されています。
「OpenAPIがあるならコードは全部自動生成でしょ」という話。これが意外と正しい選択肢だったりします。
Hey APIとは
Hey APIは、OpenAPI仕様(バージョン2.0、3.0、3.1に対応)からTypeScriptコードを生成するオープンソースのコード生成ツールです。
最大の特徴は複数のHTTPクライアントに対応していること。Fetch API、Axios、Angular HttpClient、Next.js、Nuxtなど、プロジェクトで使っているクライアントに合わせたコードを生成できます。
「One OpenAPI spec. Infinite outputs」というコンセプトで、1つのAPI仕様から様々な形式の出力が得られる設計になっています。
公式サイト: https://heyapi.dev GitHub: https://github.com/hey-api/openapi-ts
特徴・メリット
1. 完全な型安全性
生成されるコードはすべてTypeScript。リクエストパラメータ、レスポンスボディ、エラー型まで、OpenAPI仕様に基づいて厳密に型付けされます。
// 生成された型定義の例
export type User = {
id: number;
name: string;
email: string;
createdAt: string;
};
export type CreateUserRequest = {
name: string;
email: string;
};
export type CreateUserResponse = User;
IDEの補完がバッチリ効くので、タイポやパラメータの間違いをコンパイル時に検出できます。これ、意外と開発効率に直結するんですよ。
2. 複数のHTTPクライアントに対応
プロジェクトの技術スタックに合わせて、最適なクライアントを選択できます。
- Fetch API - 標準的な選択、依存関係なし
- Axios - インターセプターやキャンセルが必要な場合
- Angular - Angular HttpClientを使用
- Next.js - App RouterやServer Actionsとの統合
- Nuxt - useFetchとの統合
個人的にはFetch APIで十分なケースが多いですが、既存プロジェクトの技術選定に合わせられるのは助かります。
3. プラグインエコシステム
Hey APIはプラグイン方式を採用しており、必要な機能だけを選んで使えます。
- @hey-api/client-fetch - Fetch APIクライアント
- @hey-api/client-axios - Axiosクライアント
- @hey-api/typescript - 型定義の生成
- @hey-api/schemas - Zodなどのバリデーションスキーマ生成
- @hey-api/sdk - 高レベルなSDK生成
サードパーティの定型コードを減らして、本当に必要なものだけを生成できる設計です。コスパ的にこれはかなりデカい。
4. カスタマイズ性
生成されるコードのスタイルや構造をカスタマイズできます。カスタムプラグインやカスタムクライアントの作成にも対応しているので、独自の要件にも柔軟に対応可能です。
5. OpenAPI 3.1完全対応
最新のOpenAPI 3.1仕様に完全対応。JSON Schemaとの統合が強化された新しい仕様書でも問題なく動作します。もちろん、レガシーなOpenAPI 2.0(Swagger)やOpenAPI 3.0もサポートしています。
インストール方法
パッケージのインストール
# npm
npm install @hey-api/openapi-ts -D -E
# pnpm
pnpm add @hey-api/openapi-ts -D -E
# yarn
yarn add @hey-api/openapi-ts -D -E
# bun
bun add @hey-api/openapi-ts -D -E
重要: Hey APIはセマンティックバージョニングに従っていないため、-Eフラグで正確なバージョンをピン留めすることが推奨されています。これで予期しない破壊的変更を防げます。
クライアントパッケージのインストール
使用するHTTPクライアントに応じて、追加のパッケージをインストールします。
# Fetch APIクライアントを使用する場合
npm install @hey-api/client-fetch
# Axiosクライアントを使用する場合
npm install @hey-api/client-axios axios
基本的な使い方
最速スタート(npx)
設定ファイルなしで、すぐに試せます。
npx @hey-api/openapi-ts \
-i https://petstore3.swagger.io/api/v3/openapi.json \
-o src/client
-iでOpenAPI仕様のURLまたはファイルパスを指定し、-oで出力先ディレクトリを指定します。
設定ファイルを使う方法(推奨)
プロジェクトで継続的に使うなら、設定ファイルを作成するのがおすすめです。
// openapi-ts.config.ts
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: 'https://petstore3.swagger.io/api/v3/openapi.json',
output: 'src/client',
plugins: [
'@hey-api/typescript',
'@hey-api/client-fetch',
],
});
package.jsonにスクリプトを追加します。
{
"scripts": {
"generate:api": "openapi-ts"
}
}
これでnpm run generate:apiで実行できます。時短になりますね。
生成されるファイル構造
src/client/
├── index.ts # エクスポート
├── types.gen.ts # 型定義
├── services.gen.ts # APIサービス関数
└── schemas.gen.ts # スキーマ(オプション)
生成されたクライアントの使用
import { client } from '@hey-api/client-fetch';
import { getPetById, addPet } from './client';
// クライアントの初期設定
client.setConfig({
baseUrl: 'https://petstore3.swagger.io/api/v3',
});
// APIを呼び出す
async function main() {
// ペットを取得
const { data, error } = await getPetById({ petId: 1 });
if (error) {
console.error('エラー:', error);
return;
}
console.log('ペット:', data);
// 新しいペットを追加
const { data: newPet } = await addPet({
body: {
name: 'タマ',
photoUrls: [],
status: 'available',
},
});
console.log('追加したペット:', newPet);
}
型補完が効くので、パラメータの指定ミスが起きにくい。これがHey APIの真価です。
実践的なユースケース
1. Next.js App Routerとの統合
// openapi-ts.config.ts
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: './openapi.json',
output: 'src/api',
plugins: [
'@hey-api/typescript',
{
name: '@hey-api/client-fetch',
runtimeConfigPath: './src/api/config.ts',
},
],
});
// src/api/config.ts
import type { Config } from '@hey-api/client-fetch';
export const config: Config = {
baseUrl: process.env.NEXT_PUBLIC_API_URL,
};
// app/users/page.tsx
import { getUsers } from '@/api';
export default async function UsersPage() {
const { data: users } = await getUsers();
return (
<ul>
{users?.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Server ComponentsでもClient Componentsでも、同じAPIクライアントが使えます。
2. Zodスキーマの生成
バリデーション用にZodスキーマも自動生成できます。
// openapi-ts.config.ts
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: './openapi.json',
output: 'src/api',
plugins: [
'@hey-api/typescript',
'@hey-api/client-fetch',
{
name: '@hey-api/schemas',
type: 'zod',
},
],
});
// 生成されたスキーマを使用
import { userSchema } from '@/api/schemas.gen';
const result = userSchema.safeParse(userData);
if (!result.success) {
console.error('バリデーションエラー:', result.error);
}
フロントエンドでのフォームバリデーションと、API型定義を統一できるのは大きなメリットです。
3. 認証トークンの自動付与
import { client } from '@hey-api/client-fetch';
// 認証トークンを設定
client.setConfig({
baseUrl: 'https://api.example.com',
headers: {
Authorization: `Bearer ${getAccessToken()}`,
},
});
// または、リクエストごとに動的に設定
client.interceptors.request.use((request) => {
const token = getAccessToken();
if (token) {
request.headers.set('Authorization', `Bearer ${token}`);
}
return request;
});
4. エラーハンドリング
import { getUser } from '@/api';
async function fetchUser(id: number) {
const { data, error, response } = await getUser({ userId: id });
if (error) {
// 型安全なエラーハンドリング
if (response.status === 404) {
console.log('ユーザーが見つかりません');
return null;
}
throw new Error(`API Error: ${response.status}`);
}
return data;
}
レスポンスの型だけでなく、エラーの型も定義されているので、堅牢なエラーハンドリングが実現できます。
5. CI/CDでの自動生成
OpenAPI仕様が更新されたら、自動でクライアントを再生成するワークフローを組むと便利です。
# .github/workflows/generate-api.yml
name: Generate API Client
on:
push:
paths:
- 'openapi.json'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run generate:api
- uses: peter-evans/create-pull-request@v5
with:
commit-message: 'chore: APIクライアントを再生成'
title: 'APIクライアントの更新'
これでバックエンドの変更が自動的にフロントエンドに反映されます。
他のツールとの比較
OpenAPIからTypeScriptを生成するツールは他にもあります。
- openapi-typescript - 型定義のみを生成、軽量
- orval - React Query/SWRとの統合が強み
- openapi-generator - 多言語対応、Java製
Hey APIの強みは、型定義とクライアント生成のバランスが良いこと。過剰に複雑にならず、必要十分な機能を提供してくれます。
個人的には、シンプルなプロジェクトならHey API一択ですね。
注意点
1. OpenAPI仕様の品質が重要
生成されるコードの品質は、元のOpenAPI仕様に依存します。仕様書が不完全だと、型定義も不完全になります。バックエンドチームとの連携が大事です。
2. セマンティックバージョニング非対応
前述の通り、Hey APIはセマンティックバージョニングに従っていません。アップグレード時は必ずCHANGELOGを確認してください。
3. 生成コードのカスタマイズ制限
生成されたコードを直接編集すると、再生成時に上書きされます。カスタマイズが必要な場合は、ラッパー関数やプラグインで対応しましょう。
まとめ
正直なところ、OpenAPI仕様があるプロジェクトでHey APIを使わない理由がないんですよ。
以下の条件に当てはまるなら、導入を検討する価値は間違いなくあります:
- OpenAPI(Swagger)仕様書がある
- TypeScriptでフロントエンドを開発している
- API連携の型定義を手動で書くのが面倒
- バックエンドの変更に追従するのが大変
- Fetch、Axios、Next.js、Nuxtなどを使っている
月間310万ダウンロード、Google・Amazon・PayPalが採用という実績が、その信頼性を証明しています。
まずは既存プロジェクトのOpenAPI仕様で試してみてください。手動で書いていた型定義とfetch処理が、コマンド一発で生成される快感は格別です。QOL上がること間違いなしです。
公式サイト: https://heyapi.dev GitHub: https://github.com/hey-api/openapi-ts ドキュメント: https://heyapi.dev/openapi-ts/get-started
