飞跃高山与大洋的鱼飞跃高山与大洋的鱼
首页
先看
计算机
  • 数学
  • Linux
  • Arch
  • Manjaro
  • Ubuntu
  • CentOS
  • Kubernetes
  • Web
  • JavaScript
  • TypeScript
  • CSS
  • Canvas
  • Vue
  • Vite
  • NuxtJS
  • Webpack
  • Flutter
  • D3
  • Jest
  • WeApp
  • Utils
  • Nodejs
  • Nestjs
  • Golang
  • Nginx
  • Traefik
  • MySQL
  • MongoDB
  • Redis
  • Docker
算法
  • 像素风
  • Git
  • Github
  • VSCode
  • Chrome
  • Google
  • Bookmark scripts
  • 导航 🎉
  • VuePress 侧边栏插件
  • VuePress 官网
🚇 开往
首页
先看
计算机
  • 数学
  • Linux
  • Arch
  • Manjaro
  • Ubuntu
  • CentOS
  • Kubernetes
  • Web
  • JavaScript
  • TypeScript
  • CSS
  • Canvas
  • Vue
  • Vite
  • NuxtJS
  • Webpack
  • Flutter
  • D3
  • Jest
  • WeApp
  • Utils
  • Nodejs
  • Nestjs
  • Golang
  • Nginx
  • Traefik
  • MySQL
  • MongoDB
  • Redis
  • Docker
算法
  • 像素风
  • Git
  • Github
  • VSCode
  • Chrome
  • Google
  • Bookmark scripts
  • 导航 🎉
  • VuePress 侧边栏插件
  • VuePress 官网
🚇 开往
  • TYPESCRIPT

    • 更好维护的 TypeScript
    • 修改 axios response 返回类型
      • TypeScript 错误的类型提示
      • 解决方案
        • 1. 修改定义
        • 2. 指定返回类型
    • ESLint 在 TypeScript 未能好好工作
    • 扩展 Vue Router Meta 信息
    • TypeScript 类型挑战
    • TypeScript 常见问题

修改 axios response 返回类型

TypeScript 错误的类型提示

在 axios 相应拦截中修改了返回值:

service.interceptors.response.use(
  response => {
    return response.data
  }, 
  err => Promise.reject(err)
)

但是使用时发现返回值类型依然是 AxiosResponse<any>:

const res = axios({})
type T = typeof res
// type T = AxiosPromise<any>

解决方案

解决方案参考:How to use Axios with TypeScript when using response interceptors (AxiosResponse issue)

1. 修改定义

这并不是一个好的方案,会影响到其他内容。

// src/types/axios/axios.d.ts
import axios from 'axios'

declare module 'axios' {
  export interface AxiosInstance {
    request<T = any> (config: AxiosRequestConfig): Promise<T>;
    get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
    put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
    patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
  }
}
// tsconfig.json
{
  "compilerOptions": {
    "typeRoots": [
      "./node_modules/@types",
      "./src/types/",
    ]
  }
}

2. 指定返回类型

这是一个更好的选择,在 Allow custom return types(PR) 中:

export interface AxiosInstance {
  (config: AxiosRequestConfig): AxiosPromise;
  (url: string, config?: AxiosRequestConfig): AxiosPromise;
  defaults: AxiosRequestConfig;
  interceptors: {
    request: AxiosInterceptorManager<AxiosRequestConfig>;
    response: AxiosInterceptorManager<AxiosResponse>;
  };
  request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
  get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
  delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
  head<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
  post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
  put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
  patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
}

可以看到增加了 R 指定返回类型,当没手动制定时会根据 T 进行推导,这样就可以得到一个良好的解决方式:

interface User {
  name: string
  age: number
}

const res = axios.request<any, User>({})
type T = typeof res
// type T = Promise<User>

但作为接口而言,一般会加一层封装:

interface AxiosResponseData<T> {
  code: number
  message: string
  data?: T
}

interface User {
  name: string
  age: number
}

const res = axios.request<any, AxiosResponseData<User[]>>({})
type T = typeof res
// type T = Promise<AxiosResponseData<User[]>>

如果在响应拦截做了处理,则可以省略这一部分,毕竟每个 interface 都加这个还是有些麻烦的。

编辑文档!
上次更新:
贡献者: shanyuhai123
Prev
更好维护的 TypeScript
Next
ESLint 在 TypeScript 未能好好工作