【问题标题】:Generic return type in custom promise function自定义承诺函数中的通用返回类型
【发布时间】:2021-04-18 15:46:15
【问题描述】:

我使用泛型创建了一个可重用的函数,该函数获取数据,因此每个响应都与指定的类型匹配。如何为这个函数实现一个通用返回类型,我可以在调用该函数时指定它? (代码块 2)

const fetcher = (url: string) => {
  return new Promise(async (resolve, reject) => {
    try {
      const res = await axios.get(url, {
        headers: { Accept: "application/json" },
      });

      resolve(res.data);
    } catch (e) {
      Alert.alert(e.message);
      reject();
    }
  });
};
interface Test {
  id: number;
  title: string;
}

fetcher("test.com").then((value: Test) => {
  //  Do something with value
});

我得到的错误:

'(value: Test) => void' 类型的参数不能分配给'(value: unknown) => void | 类型的参数PromiseLike'。
参数 'value' 和 'value' 的类型不兼容。 类型“未知”不可分配给类型“测试”。 ts(2345)

【问题讨论】:

    标签: typescript promise typescript-generics


    【解决方案1】:

    您可能希望将Promise 设为Promise<any>any "type" 根本不是一个类型。相反,它会关闭对该类型值的类型检查。这将允许您将 value 回调参数注释为 Test 而不会引起编译器的投诉。

    这类似于通过Fetch API 返回的Body 对象上的json() methodtyped i n TypeScript 以返回Promise<any>。根本不是类型安全的,但它允许您在不与编译器冲突的情况下指定类型:

    const fetcher = (url: string) => {
      return new Promise<any>(async (resolve, reject) => { // <-- change on this line
        try {
          const res = await axios.get(url, {
            headers: { Accept: "application/json" },
          });
    
          resolve(res.data);
        } catch (e) {
          Alert.alert(e.message);
          reject();
        }
      });
    };
    
    
    fetcher("example.com").then((value: Test) => {
      console.log(value.id.toFixed());
    });
    

    当然,这种类型安全性的缺失意味着您,开发人员(或fetcher() 的任何用户)需要小心。没有什么能阻止你写作,例如:

    interface Other {
      id: string;
    }
    
    fetcher("example.com").then((value: Other) => {
      console.log(value.id.toUpperCase());
    });
    

    类型注释是来自发出的 JavaScript 的 erasedexample.com(有一个真正的 test.com 所以我不会用它来测试,仅供参考)不会看到两个调用之间的区别,所以它无法知道第一个调用需要number 类型的id 属性,而第二个调用需要string 类型的id 属性。因此,其中至少有一个可能会导致运行时错误。

    有更多类型安全的方法来编写此类内容,但它们将涉及类型保护,这些保护实际上会在运行时检查您的假设。但如果你只是想手动断言响应的类型并继续前进,any 可能是要走的路。

    Playground link to code

    【讨论】:

    • 感谢您的快速回复,但遗憾的是我的 linting 不允许任何类型 :{ 如果您真的认为这是我与项目经理就 linting 进行质询的唯一方法。
    • 这不是“唯一的方式”,它是与 TypeScript 处理 JSON 类型输出的库一致的方式。 JSON.parse() 返回any(await fetch("")).json() 返回Promise&lt;any&gt;;你的axios.get() 正在返回AxiosResponse&lt;any&gt;。如果您不想要any,但又不想编写一堆运行时检查,则需要执行其他同样类型不安全的操作,例如this。就我个人而言,我认为这并没有那么好。如果您被允许使用 any(如axios.get())但不能写入 any,那么也许this? ?‍♂️
    猜你喜欢
    • 2015-04-27
    • 2017-09-16
    • 2017-10-31
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2019-04-25
    • 2019-07-30
    • 2016-01-11
    相关资源
    最近更新 更多