TypeIs Does Not Properly Narrow Generics
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
When using `TypeIs` to narrow `SomeGeneric[SomeType] -> SomeType`, pyright incorrectly narrows to "object*" instead of `SomeType`. Because of this, the intersection in the other branch also cannot narrow.
**Code or Screenshots**
If possible, provide a minimal, self-contained code sample (surrounded by triple back ticks) to demonstrate the issue. The code should define or import all referenced symbols.
```python
# main.py
from typing_extensions import TypeIs, TypeVar, reveal_type
T = TypeVar("T")
type SomeType[T] = T | list[T] | set[T]
def checker[T](_: SomeType[T]) -> TypeIs[T]: ...
# TypeIs properly narrows a specific type
def logic_specific(data: SomeType[int]) -> None:
if checker(data):
reveal_type(data) # type of "data"" is "int"
else:
reveal_type(data) # type of "data" is "list[int] | set[int]"
# TypeIs seems to improperly narrow to the Generic and proper intersection
def logic_generic[T](data: SomeType[T]) -> None:
if checker(data):
reveal_type(data) # type of "data" is "object*"
else:
reveal_type(
data
) # type of "data" is "object* | list[T@logic_generic] | set[T@logic_generic]"
```
However, with mypy, I do not see this issue. `mypy main.py` will yield:
```
main.py:15: note: Revealed type is "builtins.int"
main.py:17: note: Revealed type is "Union[builtins.list[builtins.int], builtins.set[builtins.int]]"
main.py:23: note: Revealed type is "T`-1"
main.py:26: note: Revealed type is "Union[builtins.list[T`-1], builtins.set[T`-1]]"
Success: no issues found in 1 source file
```
**VS Code extension or command-line**
I have confirmed I get this issue on not just pyright, but other LSPs built ontop of it (e.g. pylance in my VSCODE (v1.100.1) and basedpyright in neovim (0.11.0) ). I have checked on the following versions of python: 3.11, 3.12, and 3.13. Note that I did have to change the syntax and such on older versions of python.
Contributor guide
Research direction
Start with the self-contained reproduction in main.py and run it through pyright, checking the reveal_type results for logic_specific and logic_generic against the expected types shown in the issue. Trace the generic TypeIs narrowing behavior from the relevant type-analysis entry point, then verify that both branches preserve T and the list/set intersection.
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
- Clearly specified
- Newbie friendliness
- 45/100