はじめに
APIとフロントエンドを連携させる際、手動で型定義を書いていると、仕様変更のたびに修正が必要です。これは時間がかかるだけでなく、ヒューマンエラーの原因にもなります。
本記事では、OpenAPI(旧Swagger)の仕様書から、TypeScriptの型定義ファイルを自動生成するopenapi-typescriptというツールを紹介します。
このツールを使えば、APIの仕様とフロントエンドのコードを常に同期させることができます。
openapi-typescriptの導入
プロジェクトにopenapi-typescript
を開発依存としてインストールします。
npm install openapi-typescript --save-dev
APIの設計図を作成する
API仕様ファイル(api.yml)の作成
OpenAPIは、APIの仕様をYAMLまたはJSONで記述します。ここでは、YAML形式でapi.yml
というファイルを作成します。
YAML形式は"
(ダブルクォート)や{}
(波括弧)、,
(コンマ)といった記号が必要ないことと、コメントを記述しやすいメリットがあるのでこちらをお勧めします。
以下ではサンプルで認証用API/auth
、ユーザー登録用API/register
、ユーザー情報取得用API/profile/{user_id}
の3つを設定しています。
projectDir/api.yml
# api.yml
# OpenAPIのバージョンを指定します。
openapi: 3.0.3
# APIの基本情報を定義します。
info:
title: My App API
version: 1.0.0
description: これは、ユーザー認証とデータ管理を行うためのAPIです。
# サーバーのURLを定義します。環境ごとにURLを分けるのが一般的です。
servers:
- url: http://localhost:5173/api
description: ローカル開発サーバー
- url: https://api.myapp.com
description: 本番サーバー
# API全体に適用される認証方式を定義します。
security:
- bearerAuth: []
# 各エンドポイントの仕様を記述します。
paths:
/auth:
post:
summary: ユーザーログイン
description: メールアドレスとパスワードでログインし、認証トークンを返します。
# ログインは認証不要なので、securityを空の配列で上書きします。
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AuthRequest"
responses:
200:
description: 認証成功
content:
application/json:
schema:
$ref: "#/components/schemas/AuthResponse"
401:
description: 認証失敗
/register:
post:
summary: 新規ユーザーの作成
description: 新しいユーザーを登録します。
# 認証後のAPIなので、セキュリティをBearerAuthに設定します。
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/User"
responses:
201:
description: 作成成功
401:
description: 認証エラー
/profile/{user_id}:
get:
summary: 特定ユーザーの情報を取得
description: 認証済みのユーザーのみがアクセス可能です。
# 認証後のAPIなので、セキュリティをBearerAuthに設定します。
security:
- bearerAuth: []
parameters:
- name: user_id
in: path
required: true
schema:
type: integer
description: ユーザーID
responses:
200:
description: 成功
content:
application/json:
schema:
# ユーザー情報をオブジェクトとして返します。
$ref: "#/components/schemas/User"
401:
description: 認証エラー
# 再利用可能なデータ型(スキーマ)や認証方式を定義します。
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
AuthRequest:
type: object
properties:
email:
type: string
password:
type: string
AuthResponse:
type: object
properties:
token:
type: string
User:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: string
型定義コマンドの設定と実行
api.yml
を作成したら、package.json
に型生成用のスクリプトを追加します。
"scripts": {
"api-types": "openapi-typescript ./api.yml --output ./src/types/api.d.ts"
}
設定後に以下のコマンドを実行すると、api.d.ts
ファイルが自動生成されます。
npm run api-types
APIファイルの作成と型の呼び出し
APIクライアントと型定義の連携
自動生成されたapi.d.ts
ファイルから、必要な型をimport type
でインポートし、APIファイルで使用します。
// src/api/usersApi.ts
import axios from "axios";
import type { AxiosInstance } from "axios";
import type { components } from "../types/api.d";
// 環境変数からAPIのベースURLを取得
const API_URL = import.meta.env.VITE_API_BASE_URL;
// スキーマをtypes/api.dから取得
type User = components["schemas"]["User"];
/**
* Axiosクライアントのインスタンス
*/
const axiosClient: AxiosInstance = axios.create({
baseURL: API_URL,
headers: {
"Content-Type": "application/json",
},
timeout: 10000, // 10秒でタイムアウト
});
/**
* ユーザー情報を取得するAPI
* @returns ユーザーデータ
*/
export const getUserProfile = async (userId: number): Promise<User> => {
const response = await axiosClient.get<User>(`${API_URL}/profile/${userId}`);
return response.data;
};
このように、openapi-typescript
を使えば、APIの仕様とフロントエンドのコードを型安全に連携させることができます。
APIの仕様に変更があった場合はapi.ymlを変更し再度npm run api-types
を実行します。
おわりに
本記事では、OpenAPIからTypeScriptの型定義を自動生成する方法を紹介しました。
この手法を導入することで、開発の効率が向上し、APIの仕様変更にも柔軟に対応できます。