I'm coding a personal project (I first started the project as Javascript) where some http requests have to be made. To do that, I decided to use Axios. So, I created a file named http.js with the following content.
import axios from 'axios';
const baseURL = '/api';
const requestWrapper = async (request, { url, options, data }) => {
const config = { baseURL, ...options };
const requestObject = await request.apply(
this,
data ? [url, data, config] : [url, config]
);
const requestData = requestObject.data;
return { status: requestObject.status, data: requestData };
};
const get = async (url, options) => {
try {
return await requestWrapper(axios.get, { url, options });
} catch (error) {
return error.response;
}
};
const remove = async (url, options) => {
try {
return await requestWrapper(axios.delete, { url, options });
} catch (error) {
return error.response;
}
};
const post = async (url, data, options) => {
try {
return await requestWrapper(axios.post, { url, data, options });
} catch (error) {
return error.response;
}
};
const put = async (url, data, options) => {
try {
return await requestWrapper(axios.put, { url, data, options });
} catch (error) {
return error.response;
}
};
const patch = async (url, data, options) => {
try {
return await requestWrapper(axios.patch, { url, data, options });
} catch (error) {
return error.response;
}
};
export { get, remove, post, put, patch };
What I did in the last code snippet is encapsulate each http request into a function named similarly. This was done to make easier the code in case the http client library (Axios) were changed.
The thing is that now I want to convert this file to Typescript. The specific problem I have, is that in the previous code I made a wrapper function because the calls for each http function are very similar, this wrapper function should receive a generic T to pass it through the Axios function in order to type the response. However, I don't know how to pass this generic because in the following function:
const requestWrapper = async (request, { url, options, data }) => {
const config = { baseURL, ...options };
const requestObject = await request.apply(
this,
data ? [url, data, config] : [url, config]
);
const requestData = requestObject.data;
return { status: requestObject.status, data: requestData };
};
Specifically:
const requestObject = await request.apply(
this,
data ? [url, data, config] : [url, config]
);
I don't know a way where i can specify the generic. What should I do?
I searched but didn't find something specific like my problem. I have thought to remove the internal wrapper and call each Axios function inside its specific encapsulation function.
CodePudding user response:
Since Function#apply
is weakly typed, you're gonna have to use a type cast if you want a stronger type:
const requestObject = await (request.apply(
this,
data ? [url, data, config] : [url, config]
) as ReturnType<typeof request<T>>)
Full code:
const requestWrapper = async <T>(request:
typeof axios.get |
typeof axios.post |
typeof axios.put |
typeof axios.patch |
typeof axios.delete
, { url, options, data }) => {
const config = { baseURL, ...options };
const requestObject = await (request.apply(
this,
data ? [url, data, config] : [url, config]
) as ReturnType<typeof request<T>>)
const requestData = requestObject.data;
return { status: requestObject.status, data: requestData };
};