首页 > 解决方案 > Typescript : 创建自定义类型 axios 实例

问题描述

我想用 axios 实例创建一个复杂的类型名称 api,这样我就可以像这样使用基本实例:

api.get("url")...

而且还能够拥有新的动态物体,例如:

api.myApi.get("url")

最后,能够像这样读取实例列表:

api.list

必须退货

我的 API

当我想扩展 AxiosInstance 或向主实例注入属性时,总是会收到类型错误。任何想法?

我的测试:

type apiInstances = Record<string, AxiosInstance>
type apiList = Record<'list', string[]>

let api: apiInstances | apiList


const instance = (baseURL: string) =>
  axios.create({
    baseURL
  })

const instances = { instance('myApi') }

api = { ...instances, ...instance(''), list }

我写的时候出错api.myApi.get("...")

'apiInstances | 类型不存在属性'myApi' apiList'

标签: javascripttypescriptaxios

解决方案


我觉得你走的很好。您可以做的最好的事情是抽象 axios 客户端,就像您对另一个 http 客户端所做的那样,并隐藏 axios 实现。为此,您可以为


export class HttpClient extends HttpMethods {
  _http: AxiosInstance;

  constructor() {
    super();
    this._http = axios.create({
      ...this._options,
      validateStatus: status => status >= 200 && status < 400,
    });
  }

  setAdditionnalHeaders(headers: object, override?: boolean): void {
    this._options = _.merge({}, override ? {} : this._options, { headers });
  }

   public async get<T>(path: string, params?: any, headers?: object): Promise<Result<T>> {
    if (headers) {
      this.setAdditionnalHeaders(headers, true);
    }
    const result = await this._http({
      method: 'GET',
      url: path,
      params,
      headers: this._options,
      ...this.hydrateConfig(this._config),
    });
    return result;
  }
}


export abstract class HttpMethods {
     public _http: any;

  protected _options: object;
public abstract get<T>(path: string, params?: any, headers?: object): Promise<Result<T>>;
}

然后使用可链接的函数,您将在其中注入隐藏 axios 在其中使用的类。

export function httpBuilder<I extends HttpMethods>(client: I): IHttpBuilder {
  return {
    ...httpRequestMethods(client),
  };
}

function httpRequestMethods(instance: HttpMethods): BuilderMethod {
  const { config } = instance;
  return {
    get<T>(path: string, params?: any, headers?: object): ChainableHttp & HttpExecutableCommand<T> {
      return {
        ...executableCommand<T>(path, instance, 'GET', requests, null, params, headers),
      };
    },
}

function executableCommand<T>(
  path: string,
  instance: HttpMethods,
  commandType: CommandType,
  requests: RequestType[],
  data?: any,
  params?: any,
  headers?: object,
): HttpExecutableCommand<T> {
  return {
    async execute(): Promise<Result<T>> {
      const result = await getResolvedResponse<T>(path, instance, commandType, data, params, headers);
      return result;
    },
  };
}

async function getResolvedResponse<T>(
  path: string,
  instance: HttpMethods,
  commandType: CommandType,
  data?: any,
  params?: any,
  headers?: object,
): Promise<Result<T>> {
  let result: Result<T>;
  if (commandType === 'GET') {
    result = await instance.get<T>(path, params, headers);
  }
  return result;
}

如果您想在您的 http 客户端上执行额外的功能,无论是 axios、fetch 还是您想要的任何东西,这是一个帮助示例:-)


推荐阅读