likes
comments
collection
share

vue3中使用ts给axios接口返回数据和传入参数约束类型

作者站长头像
站长
· 阅读数 47

前言

从vue3出来后,使用率越来越高,同时由于vue3由ts编写,对ts支持非常好

越来越多人全面拥抱 vue3+ts 的组合

那么既然用到了ts,肯定就要用好,而不是把它当成 anyScript 来使用,那样就失去了ts的使用意义了

写ts的时候,由于各种类型限制,写起来是比较繁琐的

尤其是当我们在使用 axios 的时候,我们前端本地自己写的可以限制类型

那使用接口后返回的数据该怎么定义约束这些类型呢,让我们的项目更加规范

正文

实际上在axios中也是支持ts的,让我们把它提供的类型进行结合起来

这里我把我的实现思路代码以及注释贴出,以供参考

我们需要思考并实现这几个点

  • 1、如何在请求拦截器的 请求头 上加上我们的 token类型,避免ts类型报错
  • 2、怎么在接口返回数据时约束类型
  • 3、怎么在调用接口时约束入参类型

首先我们按照正常项目思路,创建好我们的axios实例封装文件,在这里定义好相关的类型约束

创建一个 request.ts 文件并创建实例

import axios from 'axios'

/* 创建请求实例 */
const service = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
  timeout: 30000
})

然后我们需要改装一下axios自带的类型,并重新自定义为我们需要的类型

这里发现自定义的 RequestConfig 参数类型由于是在调用接口实例时使用的,所以headers非必传项

但是在拦截器器中返回的类型出了问题,请求拦截器中的参数必有 headers 字段,所以这里只能分开写成两个

// 引入 axios自带的 请求接口request参数类型 以及 请求接口headers头参数类型
import type { AxiosRequestConfig, AxiosRequestHeaders } from 'axios'

// 1、自定义请求接口headers头参数类型
type RequestHeader = AxiosRequestHeaders & { token?: string }

// 2、自定义请求接口request参数类型,可以加一些自己自定义的参数
interface RequestConfig extends AxiosRequestConfig {
  headers?: RequestHeader // 放入请求头
  noNeedToken?: boolean // 该接口是否需要token
}
interface RequestInterceptorsConfig extends RequestConfig { // 请求拦截器使用
  headers: RequestHeader;
}

然后在请求拦截器里就可以把相关的自定义参数写上去了

/* 添加请求拦截器 */
service.interceptors.request.use(
  (config: RequestInterceptorsConfig) => { // 请求拦截
    if (config.noNeedToken) { // 自定义的参数,是否不需要token的接口
      return config
    }
    const token = 'aaaaa' // 这里获取token
    if (!token) {
      return Promise.reject();
    }
    if (token) {
      config.headers.token = token // 请求头中添加token
    }
    return config
  },
  (error: AxiosError) => { // 请求错误拦截
    return Promise.reject(error);
  }
);

ts的提示出现了,类型检查生效

vue3中使用ts给axios接口返回数据和传入参数约束类型

接下来封装 request请求方法 ,约束接口返回数据类型,使用前面定义好的请求接口RequestConfig 类型

/* 封装实例的请求方法 */

// 传入泛型约束返回数据类型
// ApiResponse 主体后端返回格式
interface ApiResponse<T = any> {
  code: number;
  msg: string;
  data: T; // 这里定义请求返回data数据类型
}
export default async function request<T>(config: RequestConfig) {
  // axios实例的 request 接受的第一个泛型参数,就是返回数据data的类型
  return service.request<ApiResponse<T>>(config).then((res) => res.data); // 返回axios的里data数据
}

这里的 ApiResponse 类型是在一般情况下,我们请求后回来的data数据还会再包裹一层后端定义的状态码、消息、数据,这才是我们需要的,所以也要加上类型

vue3中使用ts给axios接口返回数据和传入参数约束类型

总算配置好了

接下来在scr下新建api文件夹,创建接口文件,引入这个axios实例并使用,直接在request方法传入后端返回的数据格式即可

import request from "../utils/request";

interface testModel {
  name: string
  age: number
}
export function test() {
  return request<testModel>({
    method: 'get',
    url: '/test',
  })
}

vue3中使用ts给axios接口返回数据和传入参数约束类型

vue3中使用ts给axios接口返回数据和传入参数约束类型

ts的提示出现了,类型检查生效

以后只需要根据后端接口文档定义好相应的返回数据类型,然后泛型传入quest方法即可

那么怎么约束入参类型呢,只需要在方法入口处限制即可

参数不对就会提示

vue3中使用ts给axios接口返回数据和传入参数约束类型

配置完成!

下面贴上完整代码

代码

文件根目录/types/axios.d.ts

import type {
  AxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosError,
} from "axios";

// 自定义请求接口headers头参数类型
type RequestHeader = AxiosRequestHeaders & { token?: string }

// 自定义请求接口request参数类型,可以加一些自己自定义的参数
export interface RequestConfig extends AxiosRequestConfig {
  headers?: RequestHeader // 放入请求头
  noNeedToken?: boolean // 该接口是否需要token
}
export interface RequestInterceptorsConfig extends RequestConfig { // 请求拦截器使用
  headers: RequestHeader;
}

// 主体后端返回格式
export interface ApiResponse<T = any> {
  code: number;
  msg: string;
  data: T; // 这里定义请求返回data数据类型
}

文件根目录/src/utils/request.ts

import axios from "axios";
import type {
  AxiosError,
} from "axios";
import type { RequestConfig, RequestInterceptorsConfig, ApiResponse } from '../../types/axios'


/* 创建请求实例 */
const service = axios.create({
  baseURL: "xxxxxxxx",
  timeout: 30000,
});

/* 添加请求拦截器 */
service.interceptors.request.use(
  (config: RequestInterceptorsConfig) => { // 请求拦截
    if (config.noNeedToken) { // 自定义的参数,是否不需要token的接口
      return config
    }
    const token = 'aaaaa' // 这里获取token
    if (!token) {
      return Promise.reject();
    }
    if (token) {
      config.headers.token = token
    }
    return config
  },
  (error: AxiosError) => { // 请求错误拦截
    return Promise.reject(error);
  }
);
/* 添加响应拦截器 */
service.interceptors.response.use();


/* 封装实例的请求方法 */
export default async function request<T>(config: RequestConfig) {
  // axios实例的 request 接受的第一个泛型参数,就是返回数据data的类型
  return service.request<ApiResponse<T>>(config).then((res) => res.data); // 返回axios的里data数据
}


文件根目录/src/api/user.ts

import request from "../utils/request";

interface testModel {
  name: string
  age: number
}

interface dataModel { // 接口入参类型
  page: number
  size: number
}

export function test(data: dataModel) {
  return request<testModel>({
    method: 'get',
    url: '/test',
    data
  })
}

test({page: 1, size: 10}).then(res => {
  console.log(res)
})
转载自:https://juejin.cn/post/7243725197911982139
评论
请登录