怎样给一个方法的属性添加类型

来源:2-2 安装 Typescript 文档

慕尼黑8466541

2022-10-10

老师晚上好!
封装了一个request,然后给它添加了一些属性,在使用它的属性是报错,具体如下,请老师帮我看一下。麻烦您了!

/**
 * axios 二次封装
 */

import axios, { AxiosRequestConfig } from 'axios'
import config from '../config'
import storage from '../utils/storage'
import router from '../router'
import { ElMessage } from 'element-plus'

interface Irequest {
  url: string
  method: string
  data?: object
  params?: object
  config?: object
}

// 创建axios实例对象,添加全局配置
const service = axios.create({
  baseURL: config.baseApi,
  timeout: 8000
})

// 请求拦截
service.interceptors.request.use((req: AxiosRequestConfig) => {
  req.headers.post['Content-Type'] = 'application/json; charset=utf-8'
  // const token = storage.getItem('token')
  // if()
  // req.?headers.post['Content-Type'] = 'application/json; charset=utf-8'
  //   const token = storage.getItem('token')
  //   if (!headers.Authorization && token) {
  //     headers.Authorization = `Bearer ${token}`
  //   }
  return req
})

// 响应拦截
service.interceptors.response.use(
  function (res) {
    const { code, msg, data } = res.data
    if (code === 0) {
      // 请求成功,返回数据
      return data
    } else if (code === 10000) {
      // 未登录 或 token超时,弹出提示信息,关闭后转跳到login
      ElMessage.error('登录超时,请重新登录!')
      return setTimeout(() => {
        router.push('/login')
      }, 1500)
    } else if (code === 10100) {
      // 无权限
      return ElMessage.error('您无此权限,请于管理员联系!')
    } else if (code === 10200) {
      // 提交数据错误
      return ElMessage.error(msg)
    } else {
      // 未知错误
      return ElMessage.error(`未知错误:${msg}`)
    }
  },
  function (error) {
    return ElMessage.error(`服务器错误:${error}`)
    // return Promise.reject(error)  // 在控制台写入错误信息
  }
)

/**
 * request 请求核心函数
 * @param options
 * @returns
 */
function request(options: Irequest) {
  // 如果method没有传,默认为get
  options.method = options.method || 'get'

  // 如果是get请求,将data赋到params,因为axios的get请求,没有data参数
  if (options.method.toLowerCase() === 'get') {
    options.params = options.data
  }

  // 防止线上环境用到mock, mock开关将不起作用
  if (config.env === 'prod') {
    service.defaults.baseURL = config.baseApi
  } else {
    service.defaults.baseURL = config.mock ? config.mockApi : config.baseApi
  }

  return service(options)
}

/**
 * 给request构造函数添加静态方法,方便调用 /* request.get() request.patch()
 * @param url
 * @param data
 * @returns
 */
const types: string[] = ['get', 'post', 'put', 'delete', 'patch']
types.forEach((item) => {
  request[item] = (url: string, data?: {}) => {
    return request({
      method: item,
      url: url,
      data: data
    })
  }
})

export default request

图片描述

图片描述

写回答

1回答

张轩

2022-10-11

同学你好 一个小问题,但是很有意思,这里你的 forEach 并没有办法自动推论,所以 get/post 这些属性都不会出现,这里要进行手动的标注:

// 先整一些类型
type HTTPMethod = 'get' | 'post' | 'put' | 'delete' | 'patch'
type IHTTPFunction = {
    [key in HTTPMethod] : (url: string, data: any) => AxiosPromise<any>
}
// 这是我们最后的类型,函数和方法的混合体
type RequestFunc =  ((options: Irequest) => AxiosPromise<any>) & IHTTPFunction

// 定义本体,伪代码,注意最后的 as
const request = ((options: Irequest) => {
    return service(options)
}) as RequestFunc
// 循环添加方法
const types: HTTPMethod[] = ['get', 'post', 'put', 'delete', 'patch']
    types.forEach((item) => {
        request[item] = (url: string, data?: any) => {
        // 省略
        })
    }
})
// 最后你会发现现在,可以联想出
request.get
0
1
慕尼黑8466541
老师,您这个研究不是一般的透,太牛了。
2022-10-14
共1条回复

Vue3 + TS 仿知乎专栏企业级项目

带你完成前后端分离复杂项目,率先掌握 vue3 造轮子技能

3142 学习 · 2313 问题

查看课程