【问题标题】:fetch written in Typescript用 Typescript 写的 fetch
【发布时间】:2019-03-14 01:11:27
【问题描述】:

我想编写一个 typescript 包装器来使用 Typescript 进行类型安全的提取。我一直在谷歌搜索,我发现最好的来源是这个thread from 2016。它似乎在 2016 年帮助了人们,但现在我没有让 sn-p 工作。

以下使 TS Linter 抱怨([ts] 预期 0 类型参数,但得到 1。):

response.json<T>()

所以根据this thread我改成如下

data => data as T

上述两个选项都不起作用,因为两个调用都返回未定义。如果使用 this 等来源,我希望能够使用 {name: string, username: string},如下所示:

api<{ name: string; username: string }>('https://jsonplaceholder.typicode.com/users')

下面的then子句:

 .then(({ name, username })

如果您能全面了解如何创建用于执行类型安全提取调用的包装函数,我们将不胜感激。

编辑

根据要求添加更完整的 sn-p

api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText);
      }
      return response.json().then(data => data as T);
    })
    .catch((error: Error) => {
      throw error;
    });
}

// consumer
this.api<{ name: string; username: string }>("https://jsonplaceholder.typicode.com/users/")
  .then(({ name, username }) => {
    console.log(name, username);
  })
  .catch(error => {
    console.error(error);
  });

【问题讨论】:

  • 你的代码是什么样子的?
  • @MuratKaragöz,现在完成了
  • 看起来不错,你用的是哪个ts版本?
  • @MuratKaragöz,版本 3.0.3

标签: typescript generics fetch


【解决方案1】:

Typescript 部分很好。在json 方法中使用as T 应该可以正常工作。

问题是您的 json 包含一个数组,而不是单个对象。因此,如果您编写 return response.json().then(data =&gt; data[0]); 仅选择一个元素,其余代码将起作用。

您可能想要整个数组,在这种情况下,您需要更改使用者以传递预期类型的​​数组:

this.api<Array<{ name: string; username: string }>>("https://jsonplaceholder.typicode.com/users/")
    .then(data  => {
       data.forEach(({ name, username }) => console.log(name, username))
    })
    .catch(error => {
      console.error(error);
    });

【讨论】:

    【解决方案2】:

    后端和前端是分开编译的,所以你不能检查你的前端/后端得到什么,但你可以使用共享的 betwen 前端和后端类型/接口并这样做:

    const res = await fetchJSON<ApiReqLogin, ApiResLogin>('api/login', { code })
    

    ApiReqLogin - 是用于此请求的类型/接口,ApiResLogin - 用于预期响应。

    在服务器上,您应该确保响应的类型为 ApiResLogin,而在前端,该请求的类型为 ApiReqLogin。

    获取包装器:

    const fetchJSON = <Req, Res>(link: string, body: Req): Promise<{ data: Res; mes: false } | { data: false; mes: string }> => {
      return new Promise(resolve => {
        fetch(link, {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(body)
        })
          .then(res => res.json())
          .then((data: Res) => {
            resolve({ data, mes: false })
          })
          .catch(err => {
            resolve({ data: false, mes: 'error' })
          })
      })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-08
      • 2021-09-25
      • 1970-01-01
      • 2017-04-27
      相关资源
      最近更新 更多