【TypeScript】Ruby on Rails APIとの型連携 - 型安全なフロントエンドとバックエンドの統合

【TypeScript】Ruby on Rails APIとの型連携 - 型安全なフロントエンドとバックエンドの統合

2024-10-26

2024-10-26

TypeScriptとRuby on Rails APIの型連携の重要性

Ruby on Railsで構築されたバックエンドAPIとTypeScriptを用いたフロントエンド間で、型定義を共有することは、型安全なデータのやり取りを実現するために非常に重要です。APIのデータ型が変更されると、フロントエンドやバックエンドのコードが正しく動作しなくなる可能性があるため、APIの型を共有して一貫性を保つことが開発の効率向上とバグの予防に役立ちます。本記事では、Rails APIとTypeScriptで型を共有するための実践的な方法を解説します。

RailsとTypeScriptの型定義共有方法

RailsとTypeScript間で型定義を共有するために、以下の方法が効果的です:

  1. OpenAPIによる型定義の自動生成
    RailsでOpenAPI仕様を使用し、その仕様からTypeScript用の型を自動生成する方法です。
  2. DTOの手動共有
    Railsで定義したDTO(Data Transfer Object)をTypeScriptで再現し、手動でデータ構造を統一する方法です。

OpenAPIを使用した型定義共有の自動化

OpenAPIはAPIの仕様を定義するフォーマットで、Railsのエンドポイント仕様からTypeScriptの型を自動生成するのに適しています。これにより、RailsでAPIのデータ型を変更しても、TypeScript側で自動的に反映できるようになります。

Step 1: RailsでOpenAPIの設定

RailsでAPI仕様を管理するために、rswagなどのGemを利用してOpenAPIドキュメントを生成します。rswagはSwagger/OpenAPIの仕様に基づいたAPIドキュメントをRailsで作成するためのツールです。

# Gemfile
gem 'rswag'
bundle install

インストール後、rswagのインストールスクリプトを実行します。

rails g rswag:install

Step 2: APIエンドポイントをOpenAPI形式で定義

rswagを使ってRailsコントローラ内でエンドポイント仕様を定義します。以下の例は、ユーザー情報を取得するAPIを定義したものです。

# spec/integration/users_spec.rb
require 'swagger_helper'
RSpec.describe 'Users API', type: :request do
  path '/users' do
    get 'Retrieves a list of users' do
      tags 'Users'
      produces 'application/json'
      response '200', 'users found' do
        schema type: :array, items: { '$ref' => '#/components/schemas/User' }
        run_test!
      end
    end
  end
end

Step 3: OpenAPIドキュメントの生成

rswagでAPI仕様に基づいたOpenAPIドキュメントを生成します。このドキュメントはJSON形式で、TypeScript用の型定義生成に利用します。

rails rswag:specs:swaggerize

Step 4: TypeScript用の型定義を自動生成

次に、生成されたOpenAPIドキュメントを基にopenapi-generator-cliを使ってTypeScript用の型を自動生成します。

npm install @openapitools/openapi-generator-cli -g
openapi-generator-cli generate -i ./swagger/v1/swagger.json -g typescript-fetch -o ./src/api

これにより、Rails APIの仕様に基づく型定義やAPIクライアントが生成され、フロントエンドで型安全にAPIを操作できるようになります。

DTOの手動同期による型定義共有

RailsとTypeScript間でDTOを手動で共有する方法もあります。Rails側で定義したDTOと同じ型をTypeScriptで再現し、データ構造の一貫性を保ちます。

Step 1: RailsでDTOを定義

まず、RailsでAPIレスポンス用のDTOをクラスとして定義します。たとえば、ユーザー情報を表現するUserDTOクラスを以下のように定義します。

# app/dto/user_dto.rb
class UserDTO
  attr_accessor :name, :email
  def initialize(name, email)
    @name = name
    @email = email
  end
end

Step 2: TypeScriptでDTOを再現

RailsのDTOクラスに基づいて、TypeScriptで同じ構造のインターフェースを定義します。

// types/UserDTO.ts
export interface UserDTO {
  name: string;
  email: string;
}

Step 3: TypeScriptでDTO型を利用

RailsのDTOと一致するDTO型をTypeScriptに定義することで、フロントエンド側で型安全なAPI呼び出しが可能になります。

// src/api/UserService.ts
import { UserDTO } from "../types/UserDTO";
export const fetchUsers = async (): Promise<UserDTO[]> => {
  const response = await fetch("/api/users");
  return await response.json();
};

型定義共有のメリットと注意点

メリット

  • データの一貫性
    型が共有されているため、フロントエンドとバックエンドで同一のデータ構造を扱うことができ、不整合が防止されます。
  • 保守性の向上
    APIの型が変更された場合にも、TypeScript側で型が自動的に更新されるため、保守が容易です。
  • 開発効率の向上
    型が共有されていると、エディタの補完機能が利用でき、開発速度が向上します。

注意点

  • バージョン管理が必要
    型定義のバージョン管理が行われていないと、フロントエンドとバックエンド間で型が異なってしまう可能性があるため、同期管理を徹底する必要があります。
  • 自動生成ツールの選定
    プロジェクトの要件や規模に応じて、最適な型生成ツールを選ぶことが重要です。ツールによっては生成されるコードや型の構造が異なります。

まとめ

TypeScriptとRuby on RailsでAPIの型定義を共有することで、データの整合性が保たれ、予期しないエラーを防ぎつつ、開発効率とメンテナンス性が向上します。OpenAPIによる自動生成やDTOの手動同期を利用して、型の一貫性を保ちながら、効率的な開発を行いましょう。

Recommend