Skip to content

Instantly share code, notes, and snippets.

@chase-moskal
Last active April 4, 2024 11:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chase-moskal/8c30b3b4bb2f102b5c5759265f5b2b47 to your computer and use it in GitHub Desktop.
Save chase-moskal/8c30b3b4bb2f102b5c5759265f5b2b47 to your computer and use it in GitHub Desktop.
Typescript function to await all promised object properties
type Unpacked<T> =
T extends (infer U)[]
? U
: T extends (...args: any[]) => infer U
? U
: T extends Promise<infer U>
? U
: T
type UnpackedObject<T> = {
[P in keyof T]: Unpacked<T[P]>
}
interface ObjInput {
[key: string]: Promise<any>
}
export async function promiseAllKeys<T extends ObjInput>(obj: T): Promise<UnpackedObject<T>> {
const operations = Object.keys(obj).map(async key => [key, await obj[key]])
const newObject = {}
for (const [key, value] of await Promise.all(operations))
newObject[key] = value
return <UnpackedObject<T>>newObject
}
@maximihajlov
Copy link

There's a new Awaited utility type starting from TS version 4.5

const all = async <T extends object>(promises: T) => {
  const result = {} as {
    [P in keyof T]: Awaited<T[P]>
  }
  for (const [key, promise] of Object.entries(promises)) {
    result[key as keyof T] = await promise
  }
  return result
}

@Nicholaiii
Copy link

Here's a version that allows parallelism, and uses the ES2019 fromEntries.

const liftKeysP = async <T extends object>(obj: T) => {
  const ops = await Promise.all(Object.entries(obj).map(async ([k, p]) => [k, await p]))
  return Object.fromEntries(ops) as {
    [P in keyof T]: Awaited<T[P]>
  }
}

@chase-moskal
Copy link
Author

@Nicholaiii yep that's super good, that version is best 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment