添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
暴走的排球  ·  XDocReport : ...·  1 年前    · 

之前用ts写了个request类方便发请求,最近想把以前写过的ts工具函数放在一起,新起了个项目。结果出现了如下的报错:

类型“(config: RequestConfig) => RequestConfig”的参数不能赋给类型“(value: InternalAxiosRequestConfig<any>) => InternalAxiosRequestConfig<any> | Promise<InternalAxiosRequestConfig<any>>”的参数。

这个RequestConfig是我自己定义的,本质上给AxiosRequestConfig添加一个拦截器的属性,如下

interface MyInterceptors {
    // 定义请求拦截和请求错误处理函数
    requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig
    requestInterceptorsCatch?: (err: any) => any
    responseInterceptors?: <T = AxiosResponse>(res: T) => T
    responseInterceptorsCatch?: (err: any) => any
// 这些拦截器实际上是放在config里面的,因此这个接口要和AxiosRequestConfig整合
export interface RequestConfig extends AxiosRequestConfig {
    interceptors?: MyInterceptors

这个错误其实是出现在request拦截器(就是那个interceptor)上的,大概意思就是拦截器里,传入和返回的参数不再是那个RequestConfig或者说是AxiosRequestConfig,而是这个新类型InternalAxiosRequestConfig

我琢磨应该是aixos版本不一样了,果然之前的版本用的是0.4几的版本,现在换成了1.4.0。

那到底AxiosRequestConfig和InternalAxiosRequestConfig这个类型有啥不同呢,我翻了一下node_modules里面axios的相关type,两者的定义如下:

AxiosRequestConfig:(因为只考察header部分,所以我把该类型的其他部分全部去掉了)

export interface AxiosRequestConfig<D = any> {
  headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;

InternalAxiosRequestConfig:

export interface InternalAxiosRequestConfig<D = any> extends AxiosRequestConfig<D> {
  headers: AxiosRequestHeaders;

这里涉及到一个新的类型AxiosRequestHeaders,定义如下

export type AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;

看样子应该是对headers属性进行了修改,那问题来了关键这个修改是什么意思呢,肯定是和ts的类型相关。

首先ts是可以通过extends的方式,修改原有对象接口的字段属性的,但是这个新的字段的类型要和原先相兼容,我写了一个例子如下

interface A {
    age?:string|number
interface C extends A{
    age:number
let example:C={age:19}

例子中A类型之中的age字段直接被覆盖掉了,原先的string|number变成了number,当然可能有人问:C当中的age变成boolean,可不可以覆盖呢,也就是如下例子

interface A {
    age?:string|number
interface C extends A{
    age:boolean
let example:C={age:true}

答案是不可以,在这种情况下C类型会给出如下错误

Interface 'C' incorrectly extends interface 'A'.
  Types of property 'age' are incompatible.
    Type 'boolean' is not assignable to type 'string | number | undefined'.(2430)

也就是C中新规制的age字段和原先的类型不兼容。

这样的话,上面那个InternalAxiosRequestConfig类型也就好理解了,就是把原先的header字段重新规制了一下

{headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders}
{headers: AxiosRequestHeaders;}
我们说type AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;
进一步转变又变成
{headers:RawAxiosRequestHeaders & AxiosHeaders}

那结合整篇文章就可以知道InternalAxiosRequestConfig和AxiosRequestConfig类型的不同,就是把headers字段中的MethodsHeaders类型排除了出来,至于这个类型为什么要排除出来呢,嘿嘿,我不知道,它是一个方法和header的键值对(类型可以参见下方),估计是给不同的方法单独配置headers用的,但是在我们的interceptors中,应该没什么用了,所以才剔除掉。感兴趣的可以去github上面看看有没有相关信息

type MethodsHeaders = Partial<{
  [Key in Method as Lowercase<Key>]: AxiosHeaders;
} & {common: AxiosHeaders}>;

最后自己写了个类似的例子

interface X{
    x:boolean
interface Y{  
    y:string
interface Z{
    z:number
interface AxiosRequestConfig{
    headers:(X&Y)|Z
interface InternalAxiosRequestConfig extends AxiosRequestConfig{
    headers:X&Z
let ex:InternalAxiosRequestConfig={
    headers:{
        x:true,
        z:19,
        //y:"hh" 这边就会报错啦
				
若依框架 axios 若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的封装若依axios的 ### 回答2: axios是一个非常流行的JavaScript库,它可以帮助开发人员在前端应用程序轻松地使用HTTP请求。使用axios时,我们经常需要传递参数到服务器,其常见的两种方式是使用data和params。 data是用于POST、PUT、DELETE等请求方法发送数据给服务器的。在axios,我们可以通过设置data属性来将数据对象发送到服务器。如果我们要使用POST或PUT请求向服务器发送数据,我们就需要将我们要发送的数据通过data属性进行设置。此时,axios会将我们的数据序列化为JSON格式,并将其添加到HTTP请求的请求体。 举个例子,如果我们要向服务器发送一个名为person的JSON对象,其包含一个名为name的属性和一个值为John的字符串,我们可以通过以下方式来设置data属性: axios.post('/api/people', { name: 'John' }).then(response => { console.log(response.data); }).catch(error => { console.log(error); params是用于GET请求将参数包含在URL的。通过params,我们可以将一些查询参数添加到我们发送的HTTP请求的URL,在URL可以看到这些参数。使用params发送请求时,axios会将我们指定的参数序列化为字符串,并将其添加到请求的URL。 举个例子,如果我们要向服务器发送一个GET请求来获取名为John的人,我们可以使用以下方式来设置params参数: axios.get('/api/people', { params: { name: 'John' }).then(response => { console.log(response.data); }).catch(error => { console.log(error); 总的来说,我们可以这样总结data和params之间的区别: - data是用于POST、PUT、DELETE等请求方法发送数据给服务器的;params是用于将参数包含在URL的GET请求的。 - 使用data时,我们需要在请求体序列化数据;使用params时,我们需要将参数序列化为字符串,并将其添加到请求的URL。 - 使用data时,数据对象会被序列化为JSON格式;使用params时,参数会被序列化为字符串。 ### 回答3: axios是一个基于Promise的HTTP客户端,用于在浏览器和Node.js等平台上发送请求。在axios,data和params是两个常用的属性,用于向服务器端发送请求时,传递参数和数据。 首先,params是GET请求的一种传参方式,它将请求参数添加到请求的URL。例如,如果您需要从https://example.com/api/getData?param1=value1&param2=value2这个URL获取数据,那么params就是param1和param2这两个参数,参数的值对应的是value1和value2。在axios,您可以这样使用params: axios.get('https://example.com/api/getData', { params: { param1: 'value1', param2: 'value2' 接着,data则是POST请求的传参方式,它将参数添加到请求的正文,用于传递复杂的数据类型。例如,如果您想要通过POST方式发送JSON数据,您可以在请求对象指定data属性,将JSON数据传递给服务器。在axios,您可以这样使用data: axios.post('https://example.com/api/postData', { key1: 'value1', key2: 'value2' 总的来说,params和data都是axios用于发送请求的属性,但它们的用途略有不同。params主要是用于GET请求,用于传递简单参数;data主要是用于POST请求,用于传递复杂数据类型。最终,您需要根据请求的类型和需要传递的数据类型,来选择合适的属性。