microsoft / microsoft/pyright

Cannot resolve `TypeDict` into `Union` *only* when the `Union` contains an `Awaitable`

Open
#11,324 0 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.