Basically the same issue as #1825 but more general.
from typing import Union
def f(a: Union[str, int]):
if a == 'a':
reveal_type(a) # expect str
str.lower(a)
test.py:6: error: Revealed type is 'Union[builtins.str, builtins.int]'
test.py:7: error: Argument 1 to "lower" of "str" has incompatible type "Union[str, int]"; expected "str"
This works if the conditional is extended with isinstance(a, str).
As noted in the referenced issue, attention must be paid to __eq__ being overrideable, meaning it cannot safely be inferred that the type of X in X == Type() is Type (or a subclass thereof) without looking into __eq__ overrides in both classes. I do not know how widely this is used for any types or for str, but I can say that I have never seen this myself. It seems that some types are more likely to compare equal to custom classes than others (e.g. None vs list), however.
Basically the same issue as #1825 but more general.
This works if the conditional is extended with
isinstance(a, str).As noted in the referenced issue, attention must be paid to
__eq__being overrideable, meaning it cannot safely be inferred that the type ofXinX == Type()isType(or a subclass thereof) without looking into__eq__overrides in both classes. I do not know how widely this is used for any types or for str, but I can say that I have never seen this myself. It seems that some types are more likely to compare equal to custom classes than others (e.g.Nonevslist), however.