You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mypy时遭遇泛型类型转换的意外类型推断问题

MyPy类型推断异常问题:为何会推断出Callable[[str], Never]?

问题背景

使用mypy 1.9.0(Python 3.12.3)进行类型检查时,遇到不符合预期的类型推断行为:mypy将预期类型错误推断为Callable[[str], Never],无法理解该错误的产生原因。

复现代码

from typing import Generic, TypeVar, Callable, reveal_type

S1 = TypeVar('S1')
F1 = TypeVar('F1')
I = TypeVar('I')


class Node(Generic[I, S1, F1]):
    def __init__(self, callback: Callable[[I], S1 | F1]):
        self.callback: Callable[[I], S1 | F1] = callback


class Succ1:
    ...


class Fail1:
    ...


def func1(_: str) -> Succ1 | Fail1:
    return Succ1()


n1 = Node(func1)
res1 = n1.callback("str")
reveal_type(n1)

MyPy报错信息

% mypy isolated_example2.py
isolated_example2.py:25: error: Need type annotation for "n1"  [var-annotated]
isolated_example2.py:25: error: Argument 1 to "Node" has incompatible type "Callable[[str], Succ1 | Fail1]"; expected "Callable[[str], Never]"  [arg-type]
isolated_example2.py:27: note: Revealed type is "isolated_example2.Node[builtins.str, Any, Any]"
Found 2 errors in 1 file (checked 1 source file)

最小复现案例

后续排查发现问题与TypeVar的联合操作相关,最小复现代码如下:

from typing import TypeVar

S1 = TypeVar('S1')
F1 = TypeVar('F1')


def func(arg: S1 | F1):
    return arg


func(None)

问题原因分析

这个问题的核心在于未绑定约束的独立TypeVar在联合类型中会被MyPy特殊处理:

  • 在Node类的定义中,S1和F1是两个无约束的独立TypeVar。当MyPy尝试推断Node的类型参数时,需要让Callable[[I], S1 | F1]与传入的Callable[[str], Succ1 | Fail1]匹配。
  • MyPy的类型推断逻辑无法自动将联合类型的分支分别绑定到独立的TypeVar上——它会认为S1 | F1需要同时满足联合类型的所有分支,而唯一能同时满足这一条件的只有Never(空类型),因此就出现了预期类型为Callable[[str], Never]的错误。
  • 最小复现案例中,MyPy同样无法确定None应该对应S1还是F1,因此也会触发类型不匹配的报错。

解决方法

  • 显式指定类型参数:给n1添加类型注解,明确各个TypeVar对应的类型,比如:
    n1: Node[str, Succ1, Fail1] = Node(func1)
    
  • 合并TypeVar并添加约束:将S1和F1合并为一个带约束的TypeVar,简化泛型定义:
    from typing import Generic, TypeVar, Callable, reveal_type
    
    I = TypeVar('I')
    Result = TypeVar('Result', Succ1, Fail1)
    
    class Node(Generic[I, Result]):
        def __init__(self, callback: Callable[[I], Result]):
            self.callback: Callable[[I], Result] = callback
    

内容的提问来源于stack exchange,提问作者Anka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:46:33