typescript axios 多个拦截器如何定义返回类型?

export interface IResponse<T = unknown> {
  data: T
  msg: string,
  total: number
}

type onFulfilled<T> = ((value: T) => T | Promise<T>) | null
type onRejected<T> = ((error: T) => T | Promise<T>) | null

interface IInterceptors {
  interceptors?: {
    request?: [onFulfilled<InternalAxiosRequestConfig>, onRejected<AxiosError>]
    response?: [onFulfilled<IResponse>, onRejected<AxiosError>]
  }
}

export class Request {
  private instance: AxiosInstance

  constructor(config: CreateAxiosDefaults & IInterceptors) {
    const { interceptors, ...restConfig } = config

    this.instance = axios.create(restConfig)

    this.instance.interceptors.response.use( // response先执行
      // 这是第一个响应拦截器,我返回了自己定义的类型
      res => res.data,
      err => err
    )

    if (interceptors?.response) { // response后执行
      // 这是第二个响应拦截器,数据类型已经不是AxiosResponse了,但是没法识别
      // 类型“onFulfilled<IResponse<unknown>>”的参数不能赋给类型“((value: AxiosResponse<any, any>) => AxiosResponse<any, any> | Promise<AxiosResponse<any, any>>) | null | undefined”的参数。
      this.instance.interceptors.response.use(...interceptors.response)
    }
  }

  async get<Req, Res>(url: string, config?: AxiosRequestConfig<Req>) {
    return await to<IResponse<Res>>(this.instance.get(url, config))
  }

  async post<Req, Res>(url: string, data: Req, config?: AxiosRequestConfig) {
    return await to<IResponse<Res>>(this.instance.post(url, data, config))
  }
}
export const request = new Request({
  baseURL: import.meta.env.VITE_BASE_URI,
  interceptors: {
    request: [
      function(config) {
        if (token.value) {
          config.headers.adminToken = token.value
        }
        return config
      },
      function(error) {
        return Promise.reject(error)
      }
    ],
    response: [
      function(response) {
        switch(response.flag) {
          case ResponseFlagEnum.unauthorized:
            token.value = ''
            userStore().removeUser()
            const route = useRoute()
            const router = useRouter()
            router.push({
              path: '/login',
              query: {
                redirect: route.fullPath
              }
            })
            ElMessage.error('用户信息过期,请重新登录')
            break
          case ResponseFlagEnum.success:
            break
          default:
            ElMessage.error(response.msg)
        }
        return response
      },
      function(error) {
        ElMessage.error(error.message)
        return Promise.reject(error)
      }
    ]
  }
})
阅读 3.3k
2 个回答

同问啊。看了半天找不到在哪里定义interceptor的类型。

老一点的版本(我用的0.27.2),interceptors.response.use是支持传一个泛型的。不知道哪个版本给去掉了...不会玩了。

建议回滚axios版本

// 老版本的AxiosInterceptorManager

export interface AxiosInterceptorManager<V> {
  use<T = V>(onFulfilled?: (value: V) => T | Promise<T>, onRejected?: (error: any) => any, options?: AxiosInterceptorOptions): number;
  eject(id: number): void;
}
// 新版本
export interface AxiosInterceptorManager<V> {
  use(onFulfilled?: ((value: V) => V | Promise<V>) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;
  eject(id: number): void;
  clear(): void;
}

如果找到办法,麻烦评论我一下,多谢

interface AxiosInterceptorManager<V> {
  use<T = V>(onFulfilled?: (value: V) => T | Promise<T>, onRejected?: (error: any) => any, options?: AxiosInterceptorOptions): number;
  eject(id: number): void;
  clear(): void;
}


(this.instance.interceptors.response.use as AxiosInterceptorManager<IResponse>['use'])(...interceptors.response)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏