我正在用Typescript编写API包装程序,并且正在考虑将Fetch API与Promises结合使用。我想在请求方法中使用泛型,以便可以对绑定到提供的类型的模型进行建模,但是我对Typescript还是很陌生(并且对此保证),并且在有条件地返回Promise<T>
或{{ 1}},因为并非所有请求都将返回一个数组。
这是我代码的状态,到目前为止,它还没有处于完成状态,但是可以使用。
Promise<T[]>
我可以尝试像这样有条件地返回:
export default class ApiWrapper
{
public async request<T>(endpoint: string, method: string = 'GET', parameters: object = {}) : Promise<void|T>
{
var protocol = process.env.REACT_APP_APPLICATION_PROTOCOL || 'https'
var host = process.env.REACT_APP_APPLICATION_HOST
var port = process.env.REACT_APP_APPLICATION_PORT ? `:${process.env.REACT_APP_APPLICATION_PORT}` : ''
var path = process.env.REACT_APP_APPLICATION_PATH || '/'
if (!host)
{
// TODO:- Handle error
}
let body = JSON.stringify(parameters)
return await fetch(`${protocol}://${host}${port}${path}/${endpoint}`, {
method: method,
body: body
})
.then(response => response.json() as Promise<T>)
.then(data => {
return data
})
}
public async get<T>(endpoint: string, parameters: object = {})
{
return await this.request<T>(endpoint, 'GET', parameters)
}
public async post(endpoint: string, parameters: object)
{
return await this.request(endpoint, 'POST', parameters)
}
public async put(endpoint: string, parameters: object)
{
return await this.request(endpoint, 'PUT', parameters)
}
public async delete(endpoint: string)
{
return await this.request(endpoint, 'DELETE')
}
}
尽管return await fetch(`${protocol}://${host}${port}${path}/${endpoint}`, {
method: method,
body: body
})
.then(response => {
if (Array.isArray(response.json())) {
return response.json() as Promise<T[]>
} else {
return response.json() as Promise<T>
}
})
.then(data => {
return data
})
无法分配给类型T
。这可能真的很简单,很愚蠢甚至不可能,但是任何指针都将不胜感激。如果有
答案 0 :(得分:1)
您不需要使用不同的签名返回相同的结果。 T
不仅可以是单一类型(例如string
,number
等),而且可以是类型的数组。
此外,我看不到函数在void
中。如果您打算抛出错误,那么正确的签名是never
。
因此,该函数可以如下所示:
class ApiWrapper {
public async request<T>(endpoint: string, method: string = "GET", parameters: object = {}): Promise<never | T> {
let protocol, host, port, path;
let body = JSON.stringify(parameters);
return await fetch(`${protocol}://${host}${port}${path}/${endpoint}`, {
method: method,
body: body
})
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error(response.statusText);
}
})
.then(data => {
return data;
});
}
}
(async () => {
const apiWrapper = new ApiWrapper();
const singleItem: string = await apiWrapper.request<string>("asdfsd");
console.log(singleItem.endsWith);
const arrayItemWrong: string[] = await apiWrapper.request<string>("asdfsd");
const arrayItem: string[] = await apiWrapper.request<string[]>("asdfsd");
console.log(arrayItem.concat);
})();
答案 1 :(得分:0)
好的,我想我已经弄明白了,尽管我确信这可能会有所缩短。
如果我使用箭头函数通过不在.then()
回调中声明Promise的返回类型,如下所示:
return await fetch(`${protocol}://${host}${port}${path}/${endpoint}`, {
method: method,
body: body
})
.then(function(response): Promise<T|T[]> {
if (response.ok) {
if (Array.isArray(response.json())) {
return response.json() as Promise<T[]>
} else {
return response.json() as Promise<T>
}
} else {
throw new Error(response.statusText)
}
})
.then(data => {
return data
})
然后,编译器似乎接受了这一点。可能应该很明显,但是TypeScript编译器错误是一个迷宫。