I have a generic function with a required transformer
generic function parameter and a generic return type T
.
I want to add a "default value" for that transformer
parameter that has a concrete type (ArrayBuffer
).
I think I've written the overload signatures correct, but my implementation does not compile.
export async function downloadWithCache(
url: string
): Promise<ArrayBuffer>;
export async function downloadWithCache<T>(
url: string,
transformer: (buffer: ArrayBuffer) => T
): Promise<T>;
export async function downloadWithCache<T>(
url: string,
transformer?: (buffer: ArrayBuffer) => T
) {
return someImplementation(url, transformer || (x => x));
}
Argument of type '((buffer: ArrayBuffer) => T) | ((x: ArrayBuffer) => ArrayBuffer)' is not assignable to parameter of type '(buffer: ArrayBuffer) => T'.
Type '(x: ArrayBuffer) => ArrayBuffer' is not assignable to type '(buffer: ArrayBuffer) => T'.
Type 'ArrayBuffer' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'ArrayBuffer'.ts(2345)
P.S. I think that someImplementation
is irrelevant, but I was asked to post it:
const httpGetDataWithCache = async <T>(
url: string,
transformer: (buffer: ArrayBuffer) => T,
cacheName: string = "cache",
updateIfInCache: boolean = false
): Promise<T> => {
const cache = await caches.open(cacheName);
let response = await cache.match(url);
let needToUpdateCache = false;
if (response === undefined || updateIfInCache) {
try {
const newResponse = await fetch(url);
if (!newResponse.ok) {
throw new Error(
`Network response was not OK: ${newResponse.status}: ${newResponse.statusText}`
);
}
response = newResponse;
needToUpdateCache = true;
} catch (err) {
if (response === undefined) {
throw err;
}
}
}
// Preventing TypeError: Failed to execute 'put' on 'Cache': Response body is already used
const responseForCaching = response.clone();
// Need to verify that the transformer executes with error before putting data in cache.
const result = transformer(await response.arrayBuffer());
if (needToUpdateCache) {
await cache.put(url, responseForCaching);
}
return result;
};
const someImplementation = httpGetDataWithCache;