Missing `TypeIs` narrowing for variadic tuples
Open
Nobody has claimed this yet.
bug
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
I noticed this behavior when investigating a similar issue in pyright.
Mypy isn't correctly narrowing tuples in some cases.
from typing_extensions import TypeIs
def is_tuple_of_strings(v: tuple[int | str, ...]) -> TypeIs[tuple[str, ...]]:
return all(isinstance(x, str) for x in v)
def test1(t: tuple[int]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be Never ✅
else:
reveal_type(t) # Should be tuple[int] ✅
def test2(t: tuple[str, int]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be Never ✅
else:
reveal_type(t) # Should be tuple[str, int] ✅
def test3(t: tuple[int | str]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be tuple[str] ✅
else:
reveal_type(t) # Should be tuple[int] or tuple[int | str] ❌ (mypy: Never)
def test4(t: tuple[int | str, int | str]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be tuple[str, str] ✅
else:
reveal_type(t) # Should be tuple[int | str, int | str] or tuple[int, int | str] | tuple[str, int] ❌ (mypy: Never)
def test5(t: tuple[int | str, ...]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be tuple[str, ...] ✅
else:
reveal_type(t) # Should be tuple[int | str, ...] ❌ (mypy: Never)
def test6(t: tuple[str, *tuple[int | str, ...], str]) -> None:
if is_tuple_of_strings(t):
reveal_type(t) # Should be tuple[str, *tuple[str, ...], str] ❌ (mypy: tuple[str, Never, str])
else:
reveal_type(t) # Should be tuple[str, *tuple[int | str, ...], str] ❌ (mypy: Never)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the six examples with mypy and comparing each reveal_type result with the expected narrowing in the issue. Trace the type-narrowing implementation for TypeIs and variadic tuples, then add regression coverage for these cases. Done means the revealed types match the expected results without regressions.
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
- 35/100