Axios post 请求与打字稿问题

Rat*_*rai 7 typescript reactjs react-typescript

我正在尝试将打字稿添加到我当前的项目中,因此在将它与 Axios post 请求一起使用后我遇到了一个问题。

用例是我想在我的帖子请求中发送“电子邮件”“名字”“姓氏”和“密码”,作为响应我想要“accessToken”

这是下面的代码

export interface UserRegistrationModel {
  email: string;
  password: string;
  firstname: string;
  lastname: string;
}



export const register = async (user: UserRegistrationModel) => {
  const { data } = await http.post<UserRegistrationModel>("/users", user);
  return data;
};
Run Code Online (Sandbox Code Playgroud)

这是我提交注册表后调用的函数,例如

register(values)
        .then((data) => {
          console.log(data.accessToken);
          setLoading(false);

        })
        .catch(() => {
          setLoading(false);

        });
Run Code Online (Sandbox Code Playgroud)

所以当我尝试通过 data.acessToken 访问“accessToken”时,在我的 then 块中会抛出错误

类型“UserRegistrationModel”上不存在属性“accessToken”

所以我尝试定义一个名为“AuthModel”的新接口,但是当我将它分配给像这样的数据时

export interface AuthModel {
  accessToken: string
}


 register(values)
        .then((data:AuthModel) => {
          console.log(data.accessToken);
          setLoading(false);
        })
        .catch(() => {
          setLoading(false);
          setSubmitting(false);
          setStatus("Registration process has broken");
        });
Run Code Online (Sandbox Code Playgroud)

它说

类型为“(data: AuthModel) => void”的参数不可分配给类型为“(value: UserRegistrationModel) => void | 的参数” 承诺喜欢'。参数“数据”和“值”的类型不兼容。“UserRegistrationModel”类型中缺少属性“accessToken”,但“AuthModel”类型中需要属性“accessToken”。

下面是任何人都想看到的 axios 配置

// http.ts

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

enum StatusCode {
  Unauthorized = 401,
  Forbidden = 403,
  TooManyRequests = 429,
  InternalServerError = 500,
}

const headers: Readonly<Record<string, string | boolean>> = {
  Accept: "application/json",
  "Content-Type": "application/json; charset=utf-8",
  "Access-Control-Allow-Credentials": true,
  "X-Requested-With": "XMLHttpRequest",
};

// We can use the following function to inject the JWT token through an interceptor
// We get the `accessToken` from the localStorage that we set when we authenticate
const injectToken = (config: AxiosRequestConfig): AxiosRequestConfig => {
  try {
    const token = localStorage.getItem("accessToken");

    if (token != null) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  } catch (error: any) {
    throw new Error(error);
  }
};

class Http {
  private instance: AxiosInstance | null = null;

  private get http(): AxiosInstance {
    return this.instance != null ? this.instance : this.initHttp();
  }

  initHttp() {
    const http = axios.create({
      baseURL: "https://api.example.com",
      headers,
      withCredentials: true,
    });

    http.interceptors.request.use(injectToken, (error) =>
      Promise.reject(error)
    );

    http.interceptors.response.use(
      (response) => response,
      (error) => {
        const { response } = error;
        return this.handleError(response);
      }
    );

    this.instance = http;
    return http;
  }

  request<T = any, R = AxiosResponse<T>>(
    config: AxiosRequestConfig
  ): Promise<R> {
    return this.http.request(config);
  }

  get<T = any, R = AxiosResponse<T>>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<R> {
    return this.http.get<T, R>(url, config);
  }

  post<T = any, R = AxiosResponse<T>>(
    url: string,
    data?: T,
    config?: AxiosRequestConfig
  ): Promise<R> {
    return this.http.post<T, R>(url, data, config);
  }

  put<T = any, R = AxiosResponse<T>>(
    url: string,
    data?: T,
    config?: AxiosRequestConfig
  ): Promise<R> {
    return this.http.put<T, R>(url, data, config);
  }

  delete<T = any, R = AxiosResponse<T>>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<R> {
    return this.http.delete<T, R>(url, config);
  }

  // Handle global app errors
  // We can handle generic app errors depending on the status code
  private handleError(error: any) {
    const { status } = error;

    switch (status) {
      case StatusCode.InternalServerError: {
        // Handle InternalServerError
        break;
      }
      case StatusCode.Forbidden: {
        // Handle Forbidden
        break;
      }
      case StatusCode.Unauthorized: {
        // Handle Unauthorized
        break;
      }
      case StatusCode.TooManyRequests: {
        // Handle TooManyRequests
        break;
      }
    }

    return Promise.reject(error);
  }
}

export const http = new Http();
Run Code Online (Sandbox Code Playgroud)

小智 9

可以设置不同类型来输入输出数据(axios 定义):

post<T = never, R = AxiosResponse<T>>(url: string, data?: T, config?: AxiosRequestConfig<T>): Promise<R>;
Run Code Online (Sandbox Code Playgroud)

所以,在你的情况下,它会是这样的:

export interface UserRegistrationModel {
  email: string;
  password: string;
  firstname: string;
  lastname: string;
}

export const register = async (user: UserRegistrationModel) => {
  const { data } = await http.post<UserRegistrationModel, AxiosResponse<{ accessToken: string }>>("/users", user);
  return data;
};
Run Code Online (Sandbox Code Playgroud)


sma*_*c89 2

将您的寄存器函数更改为:

export const register = async (user: UserRegistrationModel) => {
  const { data } = await http.post<AuthModel>("/users", user);
  return data;
};
Run Code Online (Sandbox Code Playgroud)

同样在你的班级中, 的类型post应该是:

post<T = any>(
    url: string,
    data?: T,
    config?: AxiosRequestConfig
  ): Promise<T> {
    return this.http.post(url, data, config);
}
Run Code Online (Sandbox Code Playgroud)

类型“UserRegistrationModel”上不存在属性“accessToken”

您将返回类型设置为databe UserRegistrationModel,打字稿告诉您accessToken该类型不存在。从你的定义中这应该是显而易见的。

类型为“(data: AuthModel) => void”的参数不可分配给类型为“(value: UserRegistrationModel) => void | 的参数” 承诺喜欢'。参数“数据”和“值”的类型不兼容。“UserRegistrationModel”类型中缺少属性“accessToken”,但“AuthModel”类型中需要属性“accessToken”。

您试图传递一个期望AuthModel作为唯一参数的函数,但您的函数将再次register传递UserRegistrationModel给该函数。Typescript 只是通知您这一点。