typescript :创建自定义类型axios示例

pxyaymoc  于 2023-03-18  发布在  iOS
关注(0)|答案(4)|浏览(198)

我想创建一个带有Axios示例的复杂类型名API,这样我就可以像这样使用基本示例:

api.get("url")...

而且能够具有新的动态机构,例如:

api.myApi.get("url")

最后,能够像这样阅读示例列表:

api.list

一定要回来
myApi语言
当我想扩展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|api列表'

j91ykkif

j91ykkif1#

我认为你已经走上了一条好的道路。你能做的最好的事情就是抽象出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或任何你想要的:-)

2nc8po8w

2nc8po8w2#

https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype

type ApiKeys = "myApi" | "yourApi";
type Api = Partial<Record<ApiKeys, AxiosInstance>>;
pokxtpni

pokxtpni3#

我找到了解决办法:

type Api = {
  [key: string]: AxiosInstance
  list: never
}

let api: Api

就像一个符咒

gj3fmq9x

gj3fmq9x4#

可以使用typed-axios-instance包获取路由,并将其转换为一个完全类型化的axios示例:

import type { TypedAxios } from "typed-axios-instance"
import axios from "axios"

// Need help generating these routes? You can generate them from...
// nextlove: https://github.com/seamapi/nextlove
// openapi: TODO
type Routes = [
  {
    route: "/things/create"
    method: "POST"
    jsonBody: {
      name?: string | undefined
    }
    jsonResponse: {
      thing: {
        thing_id: string
        name: string
        created_at: string | Date
      }
    }
  }
]

const myAxiosInstance: TypedAxios<Routes> = axios.create({
  baseURL: "http://example-api.com",
})

// myAxiosInstance now has intelligent autocomplete!

相关问题