I’m trying to create a utility function that will serve to extend fetch within our app, one of the things I want it to do is accept an optional Transform Function option to change the shape of the data that’s returned;
type TransformFn<TResponse, TData> = (arg0: TResponse) => TData;
interface AppFetchInit extends RequestInit {
errMsg?: string;
transformFn?: undefined;
}
interface AppFetchInitWithTransformFn<TResponse, TData> extends Omit<AppFetchInit, 'transformFn'> {
transformFn: TransformFn<TResponse, TData>;
}
interface AppFetchOverload<TResponse, TData = TResponse> {
(apiURI: string, init: AppFetchInit): TResponse;
(apiURI: string, init: AppFetchInitWithTransformFn<TResponse, TData>): TData;
}
export const appFetch: AppFetchOverload<TResponse, TData> = async (
apiURI,
{ errMsg, transformFn, ...init } = {}
) => {
const response = await fetch(apiURI, init);
if (!response.ok)
throw new Error(errMsg ?? `Fetching ${apiURI} failed: ${response.statusText}`);
const responseJson = (await response.json()) as TResponse;
return transformFn ? transformFn(responseJson) : responseJson;
};
I expect this to work, but I get errors on the implementation signature: Cannot find name 'TResponse'
and of course Cannot find name 'TData'
. This is in a .ts file, so it’s not trying to parse <TResponse, TData>
as jsx. I don’t understand why I get these errors?
Also, I’m not convinced I’m right with the AppFetchInit
and AppFetchInitWithTransformFn
interfaces – AppFetch
needs to have transformFn
as an optional property in order to be able to destructure it in the implementation signature, but to my mind wouldn’t this mean providing a transform function in a call would match the first signature and therefore type the return wrong?