首页 > 解决方案 > 导入 OpenAPI 规范生成的类型

问题描述

我正在尝试将生成的类型导入openapi-client-axiosTypescript 文件。高级设置是我有一个后端 Web 服务,从中api.json生成一个文件,为提供的休息服务创建一个 OpenAPI 规范。然后,我尝试使用该文件创建一个客户端对象,我可以使用该对象在前端 Typescript 中调用该服务。第一部分(Web 服务 -> api.json 文件)可以正常工作。我也能够成功运行:

typegen api.json > proto.d.ts

这会生成一个文件,proto.d.ts其中包含客户端键入定义。我将此文件src/types/proto.d.ts放在我的项目中,但在尝试将其导入我实际需要它的代码时遇到了麻烦。该文件src/rigging/api.ts看起来像这样:

import OpenAPIClientAxios from 'openapi-client-axios';
import { RestClient } from '@types';  // Error occurs here
// These also don't work
// import { RestClient } from './types/proto'
// import { RestClient } from 'proto'
// import { RestClient } from './types/proto.d.ts'
// import { RestClient } from 'proto.d.ts'
// import { RestClient } from '@types/proto'
// ... etc.

const api = new OpenAPIClientAxios({ definition: 'http://localhost:8000/openapi.json' });
const MyRestApi = api.getClient<RestClient>();

export default MyRestApi;

import { RestClient } ...行发生的错误似乎很明显:

TS2307:找不到模块“@types”或其对应的类型声明。

对我来说不明显的是如何解决这个问题。我尝试将proto.d.ts文件重命名为index.d.ts并移动它,但我似乎无法正确加载它。我试图弄清楚 Typescript 如何加载定义文件,但找不到正在加载的这种生成的类型定义文件的示例。

关于 Typescript、axios 和 Vue(我正在使用的框架)还有很多我不了解的地方,但在我看来,这种导入是我现在陷入的孤立问题。该@表示法似乎是在线文章所建议的,但无论是它还是点表示法(即./types/proto.d.ts)似乎都不起作用,从而导致少数其他相同的错误之一(无法找到或导入模块,错误的扩展名, ETC。)。我希望简明扼要地解释一下 Typescript 如何找到这个对象,或者解释一下我在构建这个对象时出错的地方。目前,我的文件结构是:

src/
|- main.ts
|- App.vue
|- ...
|- rigging/
|  |- api.ts
|
|- types/
   |- proto.d.ts 

在根(上src)我也有vue.config.jsand tsconfig.json,我知道这可能会影响这一点(即也许我typeRoots错了?它目前设置为[ "./types" ])但我还没有弄清楚。

如果它有用,这是生成的proto.d.ts文件:

import {
  OpenAPIClient,
  Parameters,
  // UnknownParamsObject,
  OperationResponse,
  AxiosRequestConfig,
} from 'openapi-client-axios';

declare namespace Components {
  namespace Schemas {
    export interface Codex {
      id: number; // uint64
      name: string;
    }
  }
}
declare namespace Paths {
  namespace RestApiGetCodex {
    // eslint-disable-next-line no-shadow
    namespace Parameters {
      export type Id = number; // uint64
    }
    export interface PathParameters {
      id: Parameters.Id; // uint64
    }
    namespace Responses {
      export type $200 = Components.Schemas.Codex;
    }
  }
}

export interface OperationMethods {
  /**
   * rest_api_get_codex
   */
  'rest_api_get_codex'(
    parameters?: Parameters<Paths.RestApiGetCodex.PathParameters>,
    data?: any,
    config?: AxiosRequestConfig
  ): OperationResponse<Paths.RestApiGetCodex.Responses.$200>
}

export interface PathsDictionary {
  ['/codex/{id}']: {
    /**
     * rest_api_get_codex
     */
    'get'(
      parameters?: Parameters<Paths.RestApiGetCodex.PathParameters>,
      data?: any,
      config?: AxiosRequestConfig
    ): OperationResponse<Paths.RestApiGetCodex.Responses.$200>
  }
}

export type RestClient = OpenAPIClient<OperationMethods, PathsDictionary>

标签: typescriptaxiosopenapi-generator

解决方案


事实证明,解决方案相对简单:

import OpenAPIClientAxios from 'openapi-client-axios';
import { RestClient } from '@types/proto.d';  // Only drop the 'ts' part of the extension

中的typeRoots参数tsconfig.json如下所示:

    "typeRoots": [
      "./src/types"
    ],

这使@能够引用源目录的根目录。但是,导入只删除.ts文件名的一部分,因此您必须在导入时保留该.d部分;因此from proto.d. 另一种方法是从文件系统本身的名称中删除.d,尽管这违反了定义文件约定。


推荐阅读