mcpField
O
openapi-to-typescript

openapi-to-typescript

github.com/softaworks开发2.6k4.0k 次安装34 周前更新
代码仓库

关于 openapi-to-typescript

面向开发者的技能,可将 OpenAPI 3.0 规范转换为 TypeScript 接口、请求和响应类型及类型守卫,并检查规范和处理引用。

主要功能

  1. 01验证 OpenAPI 3.0 规范
  2. 02从 Schema 生成接口
  3. 03生成端点请求与响应类型
  4. 04生成类型守卫
  5. 05处理 $ref 并报告错误

适用场景

  1. 01从 API 规范生成 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 文件

适用场景

  • “根据 OpenAPI 生成类型”
  • “将 OpenAPI 转换为 TypeScript”
  • “创建 API 接口”
  • “根据规范生成类型”

工作流

  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
格式修饰符
格式TypeScript
uuidstring(注释 UUID)
datestring(注释日期)
date-timestring(注释 ISO)
emailstring(注释电子邮件)
uristring(注释 URI)
复杂类型

对象:

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

数组:

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

枚举:

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

oneOf(联合类型):

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

allOf(交叉类型/继承):

// 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 描述用作 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()
  • 对枚举:检查 .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'
  );
}

常见错误

错误处理方式
OpenAPI 版本 != 3.0.x报告仅支持 3.0
未找到 $ref列出缺失的引用
未知类型使用 unknown 并发出警告
循环引用使用带延迟引用的类型别名

评论

支持 Markdown