I'm trying to write a method that essentially acts as a shim for Promise.allSettled, and behaves like Promise.all.
The function takes in a list of Promises (whose return types may or may not be strongly typed), runs Promise.allSettled on them, and returns an array of the results mapped to either the resolved value (if resolved), or null if not. But I want to guarantee that each item in the result array is strongly typed to the return value of its respective promise in the input array (or unknown if the promise is not strongly typed).
Here's a simplified version of what I have so far:
type Task<T> = (...args: any) => Promise<T>
/**
* Takes in a list of promises, and runs them in parallel
* If the promise resolves, return the value
* If the promise rejects, log the error and return null
*/
export async function runTasks<T>(tasks: Array<Task<T>>) {
const results = await Promise.allSettled(tasks)
return results.map((result, i) => {
if (result.status === 'rejected') {
logger.error(`Batch promise ${tasks[i].name} rejected with ${result.reason}`)
return null
}
return result.value
}) as T[] // I know this isn't right
}
I also want to give consumers the ability to explicitly type the Promise at invocation, which can look something like this.
const [hasPermission] = await runTasks([<Promise<boolean>>client.checkPermissions()])
Currently everything is coming back as unknown, but (especially when it's explicitly typed), I feel like the information I need is there, but I'm not well versed enough in generics to know how to access it. Is something like this possible?