---
url: /zh/guide/typescript/generated-client.md
description: 从一份不来自 Wow 的最小 OpenAPI 文档生成类型化的 ItemsApiClient，并检查调用方类型。
---

# 从任意 OpenAPI 文档生成客户端

`wow-generator` 也能为不来自 Wow 的 OpenAPI 文档生成客户端。要调用 Wow 服务——命令客户端、查询客户端、聚合状态——请从[快速开始](./quick-start.md)开始，那是主路径。本页讲普通情况：从纳入版本管理的文档开始，生成到独立目录，再编译调用方。本例产出确定的类和方法，不猜测生成名称。

## 1. 准备使用方项目

```bash
pnpm add @ahoo-wang/fetcher @ahoo-wang/fetcher-decorator \
  @ahoo-wang/fetcher-eventstream @ahoo-wang/fetcher-openapi \
  @ahoo-wang/wow-client
pnpm add -D @ahoo-wang/wow-generator typescript@6.0.3
```

保存以下内容为 `tsconfig.json`：

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "experimentalDecorators": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"]
}
```

## 2. 保存接口契约

将下列完整文档保存为 `openapi.json`。根标签、操作标签、operationId 和 200 响应 Schema 为生成普通类型化 API 客户端提供了必要信息。

```json
{
  "openapi": "3.0.3",
  "info": {
    "title": "Items",
    "version": "1.0.0"
  },
  "tags": [
    {
      "name": "Items"
    }
  ],
  "paths": {
    "/items/{id}": {
      "get": {
        "operationId": "getItem",
        "tags": ["Items"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Item"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Item": {
        "type": "object",
        "required": ["id"],
        "properties": {
          "id": {
            "type": "string"
          }
        }
      }
    }
  }
}
```

## 3. 生成并编译

```bash
pnpm exec wow-generator generate -i ./openapi.json -o ./src/generated -t ./tsconfig.json
pnpm exec tsc --noEmit -p ./tsconfig.json
```

每个文件都以 `// Code generated by wow-generator. DO NOT EDIT.` 开头，相对导入带 `.js` 扩展名，所以输出在 `"moduleResolution": "NodeNext"` 下也能编译。对于这份文档，输出包含 `ItemsApiClient.ts`、`types.ts` 和 `index.ts`。客户端公开 `getItem(id: string, httpRequest?: ParameterRequest, attributes?: Record<string, unknown>): Promise<Item>`，`Item` 包含必填字符串 id。如果操作声明了 query、header 参数或请求体，它们会作为带类型的参数排在 `httpRequest` 之前，必填的在前，见[方法](../../reference/typescript/wow-generator/generated-output#方法)。生成器还会写入 `.wow-generator.json`，记录输出文件所有权，并输出一行摘要，例如 `Generated 3 files into ./src/generated`。

工作目录下没有 `wow-generator.config.json` 时，CLI 按默认值生成。只有需要覆盖默认行为时再添加配置，参见[配置优先级](../../reference/typescript/wow-generator/configuration)。

## 4. 在生成目录外编写调用方

保存为 `src/loadItem.ts`，然后再次执行 TypeScript 检查：

```ts
import { Fetcher } from '@ahoo-wang/fetcher';
import { ItemsApiClient, type Item } from './generated/index.js';

export async function loadItem(baseURL: string): Promise<Item> {
  const client = new ItemsApiClient({ fetcher: new Fetcher({ baseURL }) });
  return client.getItem('42');
}
```

调用 `loadItem(yourApiOrigin)` 需要应用服务实现 `GET /items/42`、返回 JSON `{"id":"42"}`，并满足认证/CORS 配置。生成和类型检查不会发起这次远端请求。在应用入口捕获返回的 Promise。

本地运行验证可以模拟 fetch 返回 `Response.json({ id: '42' })`，调用函数后断言最终 URL 和返回 ID，并在 `finally` 中恢复 fetch。

## 5. 重新生成并审阅

修改源文档后重跑同一命令，检查模型、方法签名和所有权清单的变化后再接受差异。不要把应用代码放入 `src/generated`：在相同路径再次生成的文件会被覆盖。未修改的过时受管文件可能被删除，已经修改的过时文件会保留。生成不是目录级原子事务，失败后应检查部分输出。

缺少方法时通常应检查标签和 operationId，本次运行的警告会点名被跳过的操作（`--strict` 会让它们失败）；缺少返回类型时检查成功响应（`200`，否则最小的其他 2xx）及其媒体类型。方法名取自 operationId（`getItem`），见[方法名](../../reference/typescript/wow-generator/generated-output#方法)。Schema 编译器不是服务端验证器。此调用方在执行前不分配运行时资源，成功时会完整消费 JSON 响应。

参见 [CLI 选项](../../reference/typescript/wow-generator/cli)、[输出与重新生成](../../reference/typescript/wow-generator/generated-output)、[OpenAPI 文档](https://fetcher.ahoo.me/zh/reference/openapi/documents-and-operations)，以及独立的 [Wow 识别规则](../../reference/typescript/wow-generator/wow-discovery)。

[apiClientGenerator.ts](https://github.com/Ahoo-Wang/Wow/blob/main/typescript/wow-generator/src/client/apiClientGenerator.ts) 实现普通客户端生成。

[评估集成边界](https://fetcher.ahoo.me/zh/architecture/integration-decisions)；[返回本组任务](./index.md)。
