用 Typescript 编写的 fetch

问题描述 投票:0回答:2

我想编写一个 Typescript 包装器来使用 Typescript 进行类型安全的获取。我一直在谷歌上搜索,找到的最好的来源是 2016 年的这个线程。它似乎对 2016 年的人们有所帮助,但现在我无法让该代码片段发挥作用。

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

response.json<T>()

所以根据

这个线程我将其更改为以下

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); });
    
typescript generics fetch
2个回答
3
投票
Typescript 部分很好。在

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

0
投票
后端和前端是单独编译的,因此您无法对前端/后端获取的内容进行类型检查,但您可以在前端和后端类型/接口之间使用共享,并执行以下操作:

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' }) }) }) }
    
© www.soinside.com 2019 - 2024. All rights reserved.