FastAPIとOpenAPI-TSで型安全なフルスタックAPI開発

## OpenAPI-TS とは
OpenAPI-TS は、OpenAPI Specification を活用し、TypeScript の型システムを利用して開発を効率化するためのツール群を指します。具体的には以下のような特徴を持つツールやフレームワークが含まれます。

**1. 型定義の自動生成**
OpenAPI ドキュメントから TypeScript の型定義（types や interfaces）を自動生成します。
・リクエストパラメータの型。
・レスポンスの型。
・API エラーの型。
・型定義の自動生成により、フロントエンドとバックエンドの型整合性を保ち、型のミスを減らします。

**2. クライアントコードの自動生成**
・OpenAPI ドキュメントから、API クライアントコードを自動生成します。
・フロントエンドアプリケーションが API を呼び出す際に利用可能。
・TypeScript の型情報を活用して、安全で簡潔な API 呼び出しが可能。

**3. サーバー側のスキーマ定義**
・TypeScript を使って OpenAPI ドキュメントを定義することで、バックエンド側で API のスキーマ管理を行います。
・TypeScript で記述するため、API 定義と実装が直接リンクしやすい。

### OpenAPI-TS のメリット
**1.型安全性の向上**
TypeScript の型システムにより、API 呼び出し時のエラーを早期に発見可能。

**2.開発効率の向上**
型定義やクライアントコードの自動生成で手動作業を減らし、一貫性を確保。

**3.API 設計の統一**
OpenAPI ドキュメントを基にフロントエンドとバックエンドで統一された型を利用。

**4.保守性の向上**
OpenAPI ドキュメントに変更があれば、自動生成の型を更新するだけでコード全体の整合性を保てる。

## 信頼性の高いAPI開発
FastAPIとOpenAPI-TSを使えば、バックエンドとフロントエンドの開発を効率化し、エラーのリスクを最小限に抑えながら、スムーズに統合することができます。

例えば、あるチームが新しいプロジェクトで顧客管理システムを構築しているとします。
このシステムにはバックエンドAPIを作る必要があり、それを利用してフロントエンドが動作する仕組みです。
プロジェクトの要件には、データの整合性を保ち、将来の拡張に備えることが挙げられています。
さらに、フロントエンドの開発者とバックエンドの開発者が異なる場合、APIの仕様を明確にし、バックエンドが提供するデータを正確にフロントエンドに渡す必要があります。

しかし、チームのメンバー間でAPIの仕様が曖昧だったり、変更が適切に伝わらなかったりすると、エラーや不具合が発生する可能性が高くなります。

このようなシチュエーションでバックエンド開発者はFastAPIを使ってAPIを構築します。
たとえば、「顧客の詳細情報を取得するエンドポイント」を実装しようとすると下記のようになります。
```python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Customer(BaseModel):
    id: int
    name: str
    email: str

@app.get("/customers/{customer_id}", response_model=Customer)
def get_customer(customer_id: int):
    return {"id": customer_id, "name": "John Doe", "email": "johndoe@example.com"}
```

このコードを実行するだけで、FastAPIは自動的にSwagger UIを生成し、バックエンドAPIのインタラクティブなドキュメントを提供します。
さらに、`http://localhost:8000/openapi.json`でOpenAPI仕様も自動生成されるため、APIの設計を明確にチーム全員に共有できます。

一方、フロントエンド開発者はTypeScriptを使って開発を進めており、バックエンドが提供するAPIを呼び出して動作するWebアプリを構築しています。
ここで課題となるのは、バックエンドとフロントエンドでデータ構造が一致しているかを保証することです。

もし手動で型を定義したり、API呼び出しのコードを書いたりすれば、バックエンドが変更されるたびにフロントエンドも修正する必要があり、ミスが発生しやすくなります。

OpenAPI-TSを利用すれば、FastAPIから取得したOpenAPI仕様（openapi.json）を基に、OpenAPI-TSツールを使って型定義を自動生成できます。
```bash
npx openapi-typescript http://localhost:8000/openapi.json -o src/api-types.ts
```
これにより、以下のような型定義が生成されます。
```typescript
export interface paths {
  "/customers/{customer_id}": {
    get: {
      parameters: {
        path: {
          customer_id: number;
        };
      };
      responses: {
        200: {
          id: number;
          name: string;
          email: string;
        };
      };
    };
  };
}
```
この型定義を使えば、フロントエンド開発者は型安全にAPIを呼び出せます。
例えば、顧客情報を取得する関数は以下のように書けます。
```typescript
import { paths } from "./api-types";

async function fetchCustomer(customerId: number): Promise<paths["/customers/{customer_id}"]["get"]["responses"]["200"]> {
  const response = await fetch(`/customers/${customerId}`);
  return await response.json();
}
```
これにより、リクエストやレスポンスの型が常に保証され、バックエンド側の変更がフロントエンドに即時反映される仕組みが整います。

このように、バックエンドとフロントエンドが分離されている場合は、FastAPIとOpenAPI-TSを組み合わせることで、バックエンドとフロントエンドの間に明確な仕様を設け、変更が発生しても両者が整合性を保てるようになります。
また、コード生成により作業を自動化し、ミスを防ぎながら開発をスムーズに進めることができます。

## 開発する上での注意点

### 1. バックエンドとフロントエンドの仕様不一致
**注意点**
FastAPIが生成するopenapi.jsonをフロントエンドで使用する際、仕様が更新されるとフロントエンド側のコードが古い仕様に基づいて動作してしまうリスクがあります。この不一致は、APIの変更や追加が頻繁に行われるプロジェクトでは特に発生しやすいです。

**対策**
**・CI/CDパイプラインでの同期**
OpenAPI仕様が更新されるたびに、自動的にOpenAPI-TSで型やクライアントコードを生成し、フロントエンドのコードベースに取り込む仕組みを構築します。これにより、仕様の更新が確実に反映されます。

### 2. フロントエンドでの柔軟性の欠如
**注意点**
OpenAPI-TSで生成されたクライアントコードは型安全で便利ですが、全てのシナリオに対応できるわけではありません。例えば、エンドポイントを動的に切り替える必要がある場合や、リクエストにカスタムヘッダーを付与する場合には、生成コードが制約となることがあります。

**対策**
**・カスタムロジックの統合**
OpenAPI-TSで生成されたコードをそのまま使用するのではなく、必要に応じてラップする関数を作成し、拡張性を持たせます。

### 3. チーム間の認識のズレ
**注意点**
FastAPIとOpenAPI-TSを用いて型やクライアントを自動生成しても、チーム間で仕様や設計の意図が十分に共有されていなければ、無駄な作業やミスが発生します。

**対策**
**・ドキュメントの明確化**
Swagger UIなどの自動生成ドキュメントを活用しつつ、チーム固有のルールや設計意図を別途文書化して共有します。

**・定期的な仕様レビュー**
バックエンドとフロントエンドの開発者が定期的にミーティングを行い、OpenAPI仕様やAPIの設計について認識をすり合わせます。