【问题标题】:TypeScript can't infer promise typeTypeScript 无法推断承诺类型
【发布时间】:2020-11-01 07:37:48
【问题描述】:

我正在尝试使来自 axios 请求的响应类型安全,但在使 TypeScript 编译器正确推断类型时遇到问题。考虑以下函数,它简单地返回一个 axios 请求,该请求在 .then 块中返回所需的数据,并使用 .catch 块捕获任何错误:

interface ServerResponse {
  data: {
    User_by_pk: User;
  };
}

interface User {
  id: string;
  password: string;
}

function postRequest() {
  return axios
    .request<ServerResponse>({
      method: 'POST',
      url: 'http://example.com',
      data: someData
    })
    .then((res) => {
      return res.data.data.User_by_pk; //User type
    })
    .catch((error: AxiosError<ServerResponse>) => {
      console.log(error.message);
      return null;
    });
}

我会假设这个函数会得到返回类型Promise&lt;User | null&gt;(在.then 中返回的数据是User 类型),但是相反,它得到了返回类型Promise&lt;any&gt;。将 null 更改为 undefined 会产生相同的结果。我什至尝试显式声明函数的返回类型,但是当使用例如 let user = await postRequest(); 调用函数时,变量 user 得到的类型为 User 而不是 User | null,如预期的那样。

如果我删除 .catch 块,函数的返回类型会被正确识别为 Promise&lt;User&gt;,但一旦我添加 .catch,它就会变为 Promise&lt;any&gt; 而不是 Promise&lt;User | null&gt;

我做了一些谷歌搜索,有些人建议使用带有 Maybe 或 Result 类型的库,例如 True Myth,但如果这个功能已经内置到带有 Optionals 的 TypeScript 和?运算符(可选链接)。如何让 TypeScript 为我的函数提供正确的返回类型?

【问题讨论】:

  • 您是否尝试过使用“any”,例如:“let user: any = await postRequest();”
  • Typescript 无法知道它从服务器获得了什么,因为这是在运行时发生的。类型在运行时不存在。
  • @Evert 很抱歉,如果不清楚,但 .then 中返回的数据是 User 类型,因为我使用的是 axios.request 的类型化版本。我更新了问题以明确这一点。
  • @jcklopp 这将违背使用 TypeScript 的目的。我试图让 TypeScript 了解正确的用户类型是 User |空。
  • @Evert 如果我删除 .catch 块,则函数返回类型被正确识别为 Promise,但是一旦我添加了 .catch,它就会变成 Promise 而不是 Promise.

标签: typescript promise optional


【解决方案1】:

所以,我的 tsconfig 中出现了一个错误,导致该文件不包含在内,因此严格检查被关闭。一旦修复,我的原始代码就可以推断出正确的类型!因此,如果其他人遇到此问题,请确保已打开 strict 并且您的文件包含在 tsconfig 的 include 部分中。

为了复现,以下函数的返回类型在关闭严格时为string,在打开严格时为"true" | null。这显然是你想要的行为:)

function test(input: boolean) {
  if (input) return 'true';
  else return undefined;
}

【讨论】:

    【解决方案2】:

    尝试将函数转换为异步

    async function postRequest() {
         try {
           const response = await axios.request<ServerResponse>({
               method: "POST",
          url: "http://example.com",
          data: {}
        });
        return response.data.data.User_by_pk;
      } catch (error) {
        console.log(error.message);
        return null;
      }
    }
    

    我运行了您在代码沙箱环境中提供的代码,它似乎正在解释预期的类型,看看

    https://codesandbox.io/s/typescript-vi1l7?file=/src/index.ts

    【讨论】:

      猜你喜欢
      • 2020-12-01
      • 1970-01-01
      • 2018-07-03
      • 2021-10-29
      • 2019-09-17
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      相关资源
      最近更新 更多