Reputation: 6753
I'm trying to create a wrapper for fetch in TypeScript but I can't get the typings right:
export interface ResponsePromise extends Promise<Response> {
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
formData(): Promise<FormData>;
json<T>(): Promise<T>;
text(): Promise<string>;
}
class Api {
public get(url: string, params = {}): ResponsePromise {
const body = new URLSearchParams(params).toString();
return fetch(url, {method: 'GET', body});
}
}
const foo = async () => {
const api = new Api();
await api.get('http://www.example.com').json<any>();
}
Upvotes: 1
Views: 3748
Reputation: 1074305
TypeScript already has typings for fetch
that you can reuse:
RequestInfo
for the input
parameter (you've called it url
, but fetch
calls it input
[MDN, spec], and it may not be a string)RequestInit
for the optional init
parameter (you don't seem to be using that in your get
)Response
for the response.So:
class Api {
public get(input: RequestInfo, params = {}): Promise<Response> {
const body = new URLSearchParams(params).toString();
return fetch(input, {method: 'GET', body});
}
}
In a comment you've asked:
how do I allow the user to simply call
await api.get().json()
?
That's a very different question than a question about types. You'd probably still return Promise<Response>
, but you'd implement the first-level then
handler within get
(I do this anyway, because the fetch
API is flawed, encouraging lots of failures to handle errors as I describe here.) So for instance:
class Api {
public async get(input: RequestInfo, params = {}): Promise<Response> {
const body = new URLSearchParams(params).toString();
const response = await fetch(input, {method: 'GET', body});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
}
}
Since Response
implements Body
, it has json()
etc. on it. If you wanted, you could return Promise<Body>
instead and return .body
:
class Api {
public async get(input: RequestInfo, params = {}): Promise<Body> {
const body = new URLSearchParams(params).toString();
const response = await fetch(input, {method: 'GET', body});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.body;
}
}
...but I don't think that buys you anything.
Upvotes: 3