Smarter Type Narrowing With Intersection + Union #469
-
Consider the following python code: from enum import Enum
from typing import Generic, Literal, TypeVar
class E(Enum):
A = 0
B = 1
T = TypeVar("T", Literal[E.A], Literal[E.B])
class A(Generic[T]):
pass
class B(A[Literal[E.A]]):
pass
class C(A[Literal[E.B]]):
pass
TheUnion = B | C Now consider the following function: def a(b: A[E.A] & TheUnion) -> B:
return b. Here, there is enough information to narrow the type of the argument b to of type However, basedmypy is unable to make this narrowing, and instead says: I would love if basedmypy could correctly make this inference. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 8 replies
-
I love the idea, but unfortunately I don't believe the suggestion is entirely accurate, consider the case in which a third subclass of class D(C, A[Literal[E.A]]):
pass This class is not a Perhaps if Edit: Another feature that would make this scenario work would be from enum import Enum
from typing import Generic, Literal, TypeVar
class E(Enum):
A = 0
B = 1
T = TypeVar("T", Literal[E.A], Literal[E.B])
@sealed
class A(Generic[T]):
pass
class B(A[Literal[E.A]]):
pass
class C(A[Literal[E.B]]):
pass
def a(b: A[E.A]) -> B:
return b |
Beta Was this translation helpful? Give feedback.
-
"I love the idea, but unfortunately I don't believe the suggestion is entirely accurate, consider the case in which a third subclass of A (with E.A) is declared, the class also extends C:" I had the same thought. But when I do the following: 0: class D(C, A[Literal[E.A]]):
1: pass
2: doesnt_work: A[Literal[E.A]] = D() Line 2 get: And yes, I certainly agree with you on |
Beta Was this translation helpful? Give feedback.
After further investigation by the team, we have concluded that this example is an instance of #432.
with
A[E.A] & (B | C)
==(A[E.A] & B) | (A[E.A] & C)
. TheA[E.A] & C
should becomeNever
and disappear, leaving only theA[E.A] & B
, which simplifies toB
.I've added this example to #432. Please leave an upvote.
Thank you very much for using basedmypy and starting this discussion. 🚀