I have created a wrapper for making API calls to a Strapi server.
export const api = {
post: async<T extends unknown, K>(url: string, body: Partial<T>, jwt?: string): Promise<K> => {
try {
const result = await postData<Partial<T>, K>(url, body, jwt);
return result;
} catch (e) {
throw e;
}
},
};
My goal is to make the type K optional so I can use it like this:
await api.post<type1, type2>(url, body);
await api.post<type1>(url, body);
I attempted the following:
export const api = {
post: async<T extends unknown, K = undefined>(url: string, body: Partial<T>, jwt?: string): Promise<K | T> => {
try {
const result = await postData<Partial<T>, K | T>(url, body, jwt);
return result;
} catch (e) {
throw e;
}
},
};
However, this led to typing errors because either a field from type1 was missing in the return or the return object could possibly be undefined.
I am wondering if it's feasible to set it up so that if both types are used for the post function, the second type would be the return type, otherwise use the first type.
Below is a full example that can be pasted into TypeScript playground with comments on where the errors occur.
const api = {
post: async<T extends unknown, K = undefined>(url: string, body: Partial<T>, jwt?: string): Promise<K | T> => {
try {
const result = await postData<Partial<T>, K | T>(url, body, jwt);
return result;
} catch (e) {
throw e;
}
},
};
function postData<K, T>(url: string, data: K, jwt: string = '', failOnNotOk: boolean = true): T {
const request: T = (data) as any;
return request;
}
type user = {
email: string;
password: string;
}
type res = {
valid: string;
}
(async () => {
const url: string = 'https://google.com';
const body: user = {
email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4f3b2a3c3b0f2a372e223f232a612c2022">[email protected]</a>',
password: 'test1234',
};
// This error occurs due to result having the possibility of being undefined
const result = await api.post<user>(url, body);
console.log(result.email);
// This error occurs because 'valid' is not a field in user, when the return type should only be res
const res = await api.post<user, res>(url, body);
console.log(res.valid);
})();