next.js Typescript:如何response.data根据请求成功在前端正确输入www.example.com?

zengzsys  于 2023-02-19  发布在  TypeScript
关注(0)|答案(1)|浏览(106)

考虑以下背景:我无权查看或编辑代码的API身份验证路径返回

interface AuthSuccess {
  token: string
  user: object
}

response.data,如果电子邮件和密码正确,但返回

interface AuthError {
  error: string
}

如果error.response.data它们不正确或未在正文中传递,则返回到www.example.com。
在我的前端,内置了NextJS和axios来发出请求,我创建了以下函数来调用这个路由:

const auth = ({email, password}) =>
  api // api is the return of axios.create()
    .post(url, {email, password})
    .then((result) => ({
      success: true,
      data: response.data // here it it AuthSuccess
    }))
    .catch((error) => ({
      success: false,
      data: error.response?.data // here it is AuthError
    }))

但是当我这样调用这个函数时

const res = await auth(data)

if (res.success) {
  // here I expect data to be AuthSuccess type
} else {
  // here I expect data to be AuthError type
}

即使我在验证res.success,在if块中,Typescript的行为就像数据可以同时具有两种类型,显然它不能。
到目前为止,我已经尝试了2种解决方案:
1.将auth类型设置为(arg: AuthProps): Promise<AuthSuccess | AuthError>,这会导致if块出现问题
1.有条件地创建另一个类型:

interface AuthResult<T extends boolean> {
  success: T
  data: T extends true ? AuthSuccess : AuthError
}

auth设置为(arg: AuthProps): Promise<AuthResult>,TS抱怨没有向其传递泛型,在if块中,所有内容都变为any
那么,我怎样才能正确地输入这个函数呢?或者我怎样才能重构它来阻止这个问题呢?

xtfmy6hx

xtfmy6hx1#

您可以使用联合类型

interface SuccessResponse {
  success: true;
  data: {
    token: string;
    user: object;
  };
}

interface ErrorResponse {
  success: false;
  data: {
    error: string;
  };
}

type AuthResponse = SuccessResponse | ErrorResponse;

const test = (res: AuthResponse) => {
  if (res.success) {
    return res.data; // { token: string; user: object; }
  } else {
    return res.data; // { error: string; }
  }
}

打字操场
或者返回类型 predicate 函数:

interface SuccessResponse {
  success: true;
  data: {
    token: string;
    user: object;
  };
}

interface ErrorResponse {
  success: false;
  data: {
    error: string;
  };
}

const isSuccessResponse = (res: SuccessResponse | ErrorResponse): res is SuccessResponse => {
  return res.success;
}

const test = (res: SuccessResponse | ErrorResponse) => {
  if (isSuccessResponse(res)) {
    return res.data; // { token: string; user: object; }
  } else {
    return res.data; // { error: string; }
  }
}

打字操场

相关问题