使用 Typescript 的 SWR Vercel 全局配置 为您的问题编写了一些自定义 TypeDef

问题描述

我想用 SWR 配置创建一个对象来将它们设置为全局。我正在使用来自 swr 的 ConfigInterface 类型。

import { ConfigInterface } from 'swr';

import fetcher from 'api/axiosFetcher';

const swrConfig: ConfigInterface = {
  fetcher,};

export default swrConfig;

问题是当我尝试在 SWRConfig 中使用这个对象时

<SWRConfig value={swrConfig}>

显示一个错误

Type 'ConfigInterface<any,any,fetcherFn<any>>' is not assignable to type 'ConfigInterface<any,(...args: any) => any>'.
  Types of property 'fetcher' are incompatible.
    Type '((...args: any) => any) | null | undefined' is not assignable to type '((...args: any) => any) | undefined'.
      Type 'null' is not assignable to type '((...args: any) => any) | undefined'.ts(2322)

我的抓取功能

const fetcher = <T>(url: string): Promise<T> =>
  axiosInstance
    .get(url)
    .then((response) => {
      if (response.statusText === 'OK') {
        return response.data;
      }
      throw new Error(response.statusText);
    })
    .catch(({ response }) => {
      throw new Error(response.statusText);
    });

解决方法

为您的问题编写了一些自定义 TypeDef。

  • 首先,将您的函数编写为一个 TypeScript Class,它接受一个泛型参数 (T)。通过这种方式,您可以对应用了 Mixin 的类应用约束 (T)
type FetcherConstructor<T = {}> = new (...args: any[]) => T;

  • 我们的类只有在 url 参数传递一个字符串值时才有效——所需的 url 参数一个实现应用约束的例子(上面提到过)
type FetcherAbstracted = FetcherConstructor<{
    fetcher: (url: string,init?: RequestInit) => Promise<Response>;
}>;

如您所见,条件RequestInit接口相当广泛

interface RequestInit {
    /**
     * A BodyInit object or null to set request's body.
     */
    body?: BodyInit | null;
    /**
     * A string indicating how the request will interact with the browser's cache to set request's cache.
     */
    cache?: RequestCache;
    /**
     * A string indicating whether credentials will be sent with the request always,never,or only when sent to a same-origin URL. Sets request's credentials.
     */
    credentials?: RequestCredentials;
    /**
     * A Headers object,an object literal,or an array of two-item arrays to set request's headers.
     */
    headers?: HeadersInit;
    /**
     * A cryptographic hash of the resource to be fetched by request. Sets request's integrity.
     */
    integrity?: string;
    /**
     * A boolean to set request's keepalive.
     */
    keepalive?: boolean;
    /**
     * A string to set request's method.
     */
    method?: string;
    /**
     * A string to indicate whether the request will use CORS,or will be restricted to same-origin URLs. Sets request's mode.
     */
    mode?: RequestMode;
    /**
     * A string indicating whether request follows redirects,results in an error upon encountering a redirect,or returns the redirect (in an opaque fashion). Sets request's redirect.
     */
    redirect?: RequestRedirect;
    /**
     * A string whose value is a same-origin URL,"about:client",or the empty string,to set request's referrer.
     */
    referrer?: string;
    /**
     * A referrer policy to set request's referrerPolicy.
     */
    referrerPolicy?: ReferrerPolicy;
    /**
     * An AbortSignal to set request's signal.
     */
    signal?: AbortSignal | null;
    /**
     * Can only be null. Used to disassociate request from any Window.
     */
    window?: any;
}
  • 其中bodyInit类型定义如下
type BodyInit = Blob | BufferSource | FormData | URLSearchParams | ReadableStream<Uint8Array> | string;
  • Response 接口(在本例中为 typeof fetcher)具有以下响应接口作为其返回的负载
/** This Fetch API interface represents the response to a request. */
interface Response extends Body {
    readonly headers: Headers;
    readonly ok: boolean;
    readonly redirected: boolean;
    readonly status: number;
    readonly statusText: string;
    readonly trailer: Promise<Headers>;
    readonly type: ResponseType;
    readonly url: string;
    clone(): Response;
}

在此处查看 mixins 以获得更多说明。

  • 简单实用的实现
export default async function FetcherExample(
    fetch: FetcherAbstracted
) {
    const exactPath = 'docs/handbook/mixins.html';

    const data: Response = await new fetch().fetcher(
        `https://typescriptlang.org${exactPath}`,{
            body: exactPath,method: 'GET',headers: {
                'Content-Type': 'application/json'
                // ...
            },credentials: "include"
        }
    );

    return await data.json();
}

为了清晰起见,现在将它们全部放在一个代码片段中

export type FetcherConstructor<T = {}> = new (...args: any[]) => T;

export type FetcherAbstracted = FetcherConstructor<{
    fetcher: (url: string,init?: RequestInit) => Promise<Response>;
}>;

export default async function FetcherExample(
    fetch: FetcherAbstracted
) {
    const exactPath = 'docs/handbook/mixins.html';

    const data: Response = await new fetch().fetcher(
        `https://typescriptlang.org${exactPath}`,credentials: "include"
        }
    );

    return await data.json();
}

更新

为了简洁地回答你的问题,这个钩子应该与 axios+SWR 一起使用,这类似于我上面写的参数约束泛型

type FetcherAbstracted = FetcherConstructor<{
    fetcher: (url: string,init?: RequestInit) => Promise<Response>;
}>;

这么多,你可以将它用于你的 Axios fetcher 实现。

const fetcher: FetcherAbstracted = async (url: string) => {
  try {
    const res = await Axios.get(url);
    return res.data;
  } catch (error) {
    throw error.response.data;
  }
};

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...