mcpField
O
openapi-to-typescript

openapi-to-typescript

github.com/softaworks開発2.6k4.0k 回インストール34 週間前に更新
リポジトリ

openapi-to-typescript について

開発者向けのスキルで、OpenAPI 3.0仕様からTypeScriptのインターフェース、リクエスト・レスポンス型、型ガードを生成します。仕様の検証と参照の処理にも対応します。

主な機能

  1. 01OpenAPI 3.0仕様の検証
  2. 02スキーマからのインターフェース生成
  3. 03エンドポイントのリクエスト・レスポンス型
  4. 04型ガードの生成
  5. 05$refの処理とエラー報告

活用シーン

  1. 01API仕様からTypeScript型を生成
  2. 02エンドポイントの入出力定義を作成
  3. 03変換前にOpenAPIファイルを検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/softaworks/agent-toolkit --skill openapi-to-typescript

インストール後、Claude Code で/openapi-to-typescriptを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

OpenAPI から TypeScript

OpenAPI 3.0 の仕様を TypeScript のインターフェースと型ガードに変換します。

入力: OpenAPI ファイル(JSON または YAML) 出力: インターフェースと型ガードを含む TypeScript ファイル

使用するタイミング

  • "generate types from openapi"
  • "convert openapi to typescript"
  • "create API interfaces"
  • "generate types from spec"

ワークフロー

  1. OpenAPI ファイルのパスを尋ねる(指定されていない場合)
  2. ファイルを読み込んで検証する(OpenAPI 3.0.x である必要があります)
  3. components/schemas からスキーマを抽出する
  4. paths からエンドポイントを抽出する(リクエスト/レスポンスの型)
  5. TypeScript を生成する(インターフェース + 型ガード)
  6. 保存先を尋ねる(デフォルト: カレントディレクトリの types/api.ts)
  7. ファイルを書き込む

OpenAPI の検証

処理の前に次を確認します:

- Field "openapi" must exist and start with "3.0"
- Field "paths" must exist
- Field "components.schemas" must exist (if there are types)

無効な場合は、エラーを報告して停止します。

型のマッピング

プリミティブ
OpenAPITypeScript
stringstring
numbernumber
integernumber
booleanboolean
nullnull
フォーマット修飾子
FormatTypeScript
uuidstring (comment UUID)
datestring (comment date)
date-timestring (comment ISO)
emailstring (comment email)
uristring (comment URI)
複合型

Object:

// OpenAPI: type: object, properties: {id, name}, required: [id]
interface Example {
  id: string;      // required: no ?
  name?: string;   // optional: with ?
}

Array:

// OpenAPI: type: array, items: {type: string}
type Names = string[];

Enum:

// OpenAPI: type: string, enum: [active, draft]
type Status = "active" | "draft";

oneOf (Union):

// OpenAPI: oneOf: [{$ref: Cat}, {$ref: Dog}]
type Pet = Cat | Dog;

allOf (Intersection/Extends):

// OpenAPI: allOf: [{$ref: Base}, {type: object, properties: ...}]
interface Extended extends Base {
  extraField: string;
}

コード生成

ファイルヘッダー
/**
 * Auto-generated from: {source_file}
 * Generated at: {timestamp}
 *
 * DO NOT EDIT MANUALLY - Regenerate from OpenAPI schema
 */
インターフェース(components/schemas から)

components/schemas の各スキーマについて:

export interface Product {
  /** Product unique identifier */
  id: string;

  /** Product title */
  title: string;

  /** Product price */
  price: number;

  /** Created timestamp */
  created_at?: string;
}
  • OpenAPI の description を JSDoc として使用する
  • required[] にあるフィールドには ? を付けない
  • required[] にないフィールドには ? を付ける
リクエスト/レスポンスの型(paths から)

paths の各エンドポイントについて:

// GET /products - query params
export interface GetProductsRequest {
  page?: number;
  limit?: number;
}

// GET /products - response 200
export type GetProductsResponse = ProductList;

// POST /products - request body
export interface CreateProductRequest {
  title: string;
  price: number;
}

// POST /products - response 201
export type CreateProductResponse = Product;

命名規則:

  • パラメーターとボディには {Method}{Path}Request
  • レスポンスには {Method}{Path}Response
型ガード

主要な各インターフェースについて、型ガードを生成します:

export function isProduct(value: unknown): value is Product {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    typeof (value as any).id === 'string' &&
    'title' in value &&
    typeof (value as any).title === 'string' &&
    'price' in value &&
    typeof (value as any).price === 'number'
  );
}

型ガードのルール:

  • typeof value === 'object' && value !== null を確認する
  • 必須の各フィールドについて 'field' in value を確認する
  • プリミティブのフィールドについては typeof を確認する
  • 配列については Array.isArray() を確認する
  • enum については .includes() を確認する
エラー型(常に含める)
export interface ApiError {
  status: number;
  error: string;
  detail?: string;
}

export function isApiError(value: unknown): value is ApiError {
  return (
    typeof value === 'object' &&
    value !== null &&
    'status' in value &&
    typeof (value as any).status === 'number' &&
    'error' in value &&
    typeof (value as any).error === 'string'
  );
}

$ref の解決

{"$ref": "#/components/schemas/Product"} に遭遇した場合:

  1. スキーマ名(Product)を抽出する
  2. その型をそのまま使用する(インラインで解決しない)
// OpenAPI: items: {$ref: "#/components/schemas/Product"}
// TypeScript:
items: Product[]  // reference, not inline

完全な例

入力(OpenAPI):

{
  "openapi": "3.0.0",
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "email": {"type": "string", "format": "email"},
          "role": {"type": "string", "enum": ["admin", "user"]}
        },
        "required": ["id", "email", "role"]
      }
    }
  },
  "paths": {
    "/users/{id}": {
      "get": {
        "parameters": [{"name": "id", "in": "path", "required": true}],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/User"}
              }
            }
          }
        }
      }
    }
  }
}

出力(TypeScript):

/**
 * Auto-generated from: api.openapi.json
 * Generated at: 2025-01-15T10:30:00Z
 *
 * DO NOT EDIT MANUALLY - Regenerate from OpenAPI schema
 */

// ============================================================================
// Types
// ============================================================================

export type UserRole = "admin" | "user";

export interface User {
  /** UUID */
  id: string;

  /** Email */
  email: string;

  role: UserRole;
}

// ============================================================================
// Request/Response Types
// ============================================================================

export interface GetUserByIdRequest {
  id: string;
}

export type GetUserByIdResponse = User;

// ============================================================================
// Type Guards
// ============================================================================

export function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    typeof (value as any).id === 'string' &&
    'email' in value &&
    typeof (value as any).email === 'string' &&
    'role' in value &&
    ['admin', 'user'].includes((value as any).role)
  );
}

// ============================================================================
// Error Types
// ============================================================================

export interface ApiError {
  status: number;
  error: string;
  detail?: string;
}

export function isApiError(value: unknown): value is ApiError {
  return (
    typeof value === 'object' &&
    value !== null &&
    'status' in value &&
    typeof (value as any).status === 'number' &&
    'error' in value &&
    typeof (value as any).error === 'string'
  );
}

よくあるエラー

ErrorAction
OpenAPI version != 3.0.xReport that only 3.0 is supported
$ref not foundList missing refs
Unknown typeUse unknown and warn
Circular referenceUse type alias with lazy reference

コメント