将 api 服务更新为打字稿 - TS2339:属性 'instance' 在类型 'Http' 上不存在

Updating api service to typescript - TS2339: Property 'instance' does not exist on type 'Http'

为什么我的实例说它在 Http 上不存在?

我正在使用我的实例 return 我将进行哪种类型的 axios 调用 - get/post 等等。

    constructor(baseURL: string, headers = {}, config = {}, interceptors = null, timeout = 8000) {
    this.instance = axios.create({
        headers,
        timeout,
        baseURL,
        ...config,
    });

    if (interceptors) {
        interceptors.hook(this.instance);
    }
}

属性 'instance' 在类型 'Http'

上不存在

在打字稿中创建 class 时,您需要声明所有 class 属性及其类型。

import axios, {AxiosInstance, AxiosRequestConfig} from "axios";

class Http {
    public instance: AxiosInstance;

    /* ...  */
}

当您使用 body-less 构造函数将构造函数参数设置为实例变量时,您可以绕过此要求。但是在这种情况下,您要在构造函数中创建一个 属性,因此您需要在 class.

的顶层声明它

Object 可能是 'null'

此外,您需要为一些构造函数参数声明类型,因为它们无法被正确推断。基本上打字稿采用默认值的类型,并假定默认值的类型是参数的类型。所以 timeout = 8000 很好,因为 timeout 被假定为 number(尽管我个人还是添加了类型以保持一致性)。

但是 interceptors = null 会导致问题,因为 typescript 不知道 interceptors 的类型应该是什么,而它不是 null。它实际上将 interceptors 的类型分配为 null,所以即使在检查它存在之后你仍然会得到一个错误 Object is possibly 'null'.

您可能已经在您的代码库中的某处为这个 object 创建了一个类型,但仅基于此代码片段,它必须有一个 属性 hook 可以让您实例:

interface Interceptors {
    hook( instance: AxiosInstance ): void;
}

为了使用 null 作为默认值,我们不得不说这个变量可以是 Interceptors | null.

对于 headers 和配置,这些需要输入为 axios 可以接受的内容。 AxiosRequestConfig 实际上说 headers 可以是 any,但让我们将其限制为 string-keyed object 又名 Record<string, any>. For the config we'll just use the AxiosRequestConfig type we imported from axios. We could get fancy and Omit 我们正在覆盖的属性, 但这是不必要的,因为它们已经是可选的。

正确类型的构造函数可能类似于

    constructor(
        baseURL: string,
        headers: Record<string, any> = {},
        config: AxiosRequestConfig = {},
        interceptors: Interceptors | null = null,
        timeout: number = 8000
    ) {

Typescript Playground Link