以打字稿获取

时间:2018-10-09 09:43:38

标签: typescript generics fetch

我想编写一个Typescript包装器,以使用Typescript进行类型安全的访存。我一直在四处搜寻,发现的最佳资源是这个thread from 2016。它似乎在2016年帮助了人们,但是现在我没有得到摘要的帮助。

以下使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 })

对于如何创建用于执行类型安全的访存调用的包装器功能的全面介绍,将是感激的。

编辑

根据要求添加更完整的代码段

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);
  });

2 个答案:

答案 0 :(得分:1)

“打字稿”部分很好。在as T方法中使用json应该可以正常工作。

问题是您的json包含数组,而不是单个对象。因此,如果您编写return response.json().then(data => 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);
    });

答案 1 :(得分:0)

后端和前端是分开编译的,因此您不能类型检查前端/后端得到什么,但是您可以使用共享的bettwen前端和后端类型/接口并执行以下操作:

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' })
      })
  })
}