Cannot resolve `TypeDict` into `Union` *only* when the `Union` contains an `Awaitable`
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
I'm seeing `pyright` fail to type a `TypedDict` **only** when it's resolved into a union that includes a third type (in my example, `Awaitable[T]`). Here is my repro:
```python
from typing import Awaitable, Callable, Generic, TypedDict, TypeVar, Union
T = TypeVar("T")
U = TypeVar("U")
Input = Union[T, Awaitable[T], "Output[T]"]
class Output(Generic[T]):
def apply(self, func: Callable[[T], Input[U]]) -> "Output[U]": ...
class D(TypedDict):
key: str
def accept(x: Input[list[D]]) -> None: ...
# OK: dict literal directly in call has downward type context.
accept([{"key": "v"}])
# ERROR: dict literal inside apply lambda is inferred as dict[str, str], not D.
accept(Output[list[D]]().apply(lambda _: [{"key": "v"}]))
```
The confusing this is that this makes it type-check without errors:
```patch
-Input = Union[T, Awaitable[T], "Output[T]"]
+Input = Union[T, "Output[T]"]
```
Full non-erroring code
```python
from typing import Awaitable, Callable, Generic, TypedDict, TypeVar, Union
T = TypeVar("T")
U = TypeVar("U")
Input = Union[T, "Output[T]"]
class Output(Generic[T]):
def apply(self, func: Callable[[T], Input[U]]) -> "Output[U]": ...
class D(TypedDict):
key: str
def accept(x: Input[list[D]]) -> None: ...
# OK: dict literal directly in call has downward type context.
accept([{"key": "v"}])
# ERROR: dict literal inside apply lambda is inferred as dict[str, str], not D.
accept(Output[list[D]]().apply(lambda _: [{"key": "v"}]))
```
This was observed running the `pyright` CLI at version 1.1.408.
---
Notes:
`mypy --strict` (at version 0.931) type-checks both programs without issue.
https://github.com/microsoft/pyright/issues/10908 implies that these programs should never type-check, but that obviously the case.
Contributor guide
Research direction
Start by reproducing the minimal examples from the issue with the pyright CLI at version 1.1.408, comparing diagnostics with and without Awaitable[T] in Input. Trace the type inference involved in the lambda and TypedDict union, then verify that the intended behavior is covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100