I can write a function like
async def par_all(fns: tuple[Awaitable[T], Awaitable[U]]) -> tuple[T,U]: ...
But how do I extend this to take tuples of any size, without losing type info? (And ideally not *fns
, but I’m fine if it needs to be that.)
Tried something like this but it doesn’t quite work, at least not with pyright.
from typing import Awaitable, TypeVarTuple, Unpack
Ts = TypeVarTuple('Ts')
async def par_all(fns: tuple[Awaitable[Unpack[Ts]], ...]) -> tuple[Unpack[Ts]]:
return await asyncio.gather(*fns)
import asyncio
async def foo() -> int:
await asyncio.sleep(1)
return 1
async def bar() -> str:
await asyncio.sleep(1)
return "hello"
async def baz() -> float:
await asyncio.sleep(1)
return 3.14
async def main():
result = await par_all((foo(), bar(), baz()))
print(result) # (1, "hello", 3.14)
# The type of result should be tuple[int, str, float], but no luck!
asyncio.run(main())
(And additionally, what’s the best way to alternatively take a Iterable[Awaitable[T]]
and return a tuple[T]
—just with overloads?)