Bug Report
With Python >= 3.13, given cls: type[A] and if issubclass(cls, M) where A and M are dataclasses, mypy is unable to narrow the type of cls to type[M]. Instead, the guarded block is not typechecked at all.
When iterating over a list[type[A]] in a comprehension with if issubclass(cls, M) where A and M are dataclasses, mypy is unable to narrow the type of cls to type[M]. Instead, the comprehension result expression is typechecked with cls at its original unnarrowed type type[A].
To Reproduce
from dataclasses import dataclass
from typing import reveal_type
@dataclass
class A:
pass
@dataclass
class M:
pass
@dataclass
class B(A):
pass
@dataclass
class C(M, A):
pass
cls: type[A] = C
if issubclass(cls, M):
reveal_type(cls)
n: int = 'foo'
Expected Behavior
The type of cls is revealed as type[M], followed by a type error for the assignment of a str to a variable of type int.
Actual Behavior
No type is revealed, silent success.
For comprehensions:
from dataclasses import dataclass
from typing import reveal_type
@dataclass
class A:
pass
@dataclass
class M:
pass
@dataclass
class B(A):
pass
@dataclass
class C(M, A):
pass
alist: list[type[A]] = [B, C]
mlist = [cls for cls in alist if issubclass(cls, M)]
reveal_type(mlist)
Expected Behavior
note: Revealed type is "list[type[<subclass of "A" and "M">]]"
And if we annotate mlist: list[type[M]] it still typechecks.
Actual Behavior
note: Revealed type is "list[type[A]]"
And if we annotate mlist: list[type[M]] we get:
error: List comprehension has incompatible type List[type[A]]; expected List[type[M]] [misc]
Notes
This error DOES NOT occur if the classes are not dataclasses.
This error DOES NOT occur in a regular for loop:
mlist: list[type[M]] = []
cls: type[A]
for cls in alist:
if issubclass(cls, M):
mlist.append(cls)
This error DOES still occur if issubclass() is wrapped in a TypeIs guard function:
def is_m(t: type) -> TypeIs[type[M]]:
return issubclass(t, M)
alist: list[type[A]] = [B, C]
mlist: list[type[M]] = [cls for cls in alist
if is_m(cls)]
Your Environment
- Mypy version used: mypy 2.1.0 (compiled: no)
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini (and other config files): nothing special
- Python version used: 3.13.13
Bug Report
With Python >= 3.13, given
cls: type[A]andif issubclass(cls, M)where A and M are dataclasses, mypy is unable to narrow the type ofclstotype[M]. Instead, the guarded block is not typechecked at all.When iterating over a
list[type[A]]in a comprehension withif issubclass(cls, M)where A and M are dataclasses, mypy is unable to narrow the type ofclstotype[M]. Instead, the comprehension result expression is typechecked withclsat its original unnarrowed typetype[A].To Reproduce
Expected Behavior
The type of
clsis revealed astype[M], followed by a type error for the assignment of astrto a variable of typeint.Actual Behavior
No type is revealed, silent success.
For comprehensions:
Expected Behavior
And if we annotate
mlist: list[type[M]]it still typechecks.Actual Behavior
And if we annotate
mlist: list[type[M]]we get:Notes
This error DOES NOT occur if the classes are not dataclasses.
This error DOES NOT occur in a regular for loop:
This error DOES still occur if
issubclass()is wrapped in a TypeIs guard function:Your Environment
mypy.ini(and other config files): nothing special