Missing `TypeIs` narrowing for variadic tuples
未关闭
还没有人认领这个 Issue。
bug
- 主要语言
- Python
- 星标
- 20.6k
- 派生
- 3.3k
- PR 合并指标
- PR 指标待抓取
描述
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)
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
首先使用 mypy 重现这六个示例,并将每个 reveal_type 结果与 issue 中预期的类型收窄进行比较。跟踪 TypeIs 和可变元组的类型收窄实现,然后为这些情况添加回归覆盖。完成的标准是 reveal 出的类型与预期结果一致,且没有回归。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- devtools
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100