-
I think this is a bug, but I wasn't sure so I started a discussion instead of an issue. As far as I know, Here's a minimal reproduction: from typing import Optional, Union
def func(arg1: Union[str, int]) -> None:
if isinstance(arg1, str):
if arg1 is None:
x = 1
else:
x = 1000
reveal_type(x) # reveals Literal[1, 1000]. I believe it should be Literal[1000]. If this seems obscure/unlikely to happen in real life, that's because it's my attempt to distill a real life scenario into a minimal repro. The real life situation is more like: from typing import Optional, Union
import random
from library_without_types import NoneExistent # type: ignore
def func(arg1: Union[str, NoneExistent]) -> None:
var1: Optional[str] = "some string" if random.random() > 0.5 else None
if isinstance(arg1, str):
if var1 is None:
var1 = arg1
reveal_type(var1) # reveals str | None, I think it should be str That 1 I suppose it's possible that classes override |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
In the first code snippet, you have annotated In the second code snippet, pyright will do the right thing if it knows the type of If I replace the import with a minimal definition for from typing import Optional, Union
class NoneExistent:
pass
def func(arg1: Union[str, NoneExistent]) -> None:
if isinstance(arg1, str):
var1: Optional[str] = None
if var1 is None:
var1 = arg1
reveal_type(var1) # reveals str This is a good demonstration of why it's so important to have good type information for the libraries you import. |
Beta Was this translation helpful? Give feedback.
In the first code snippet, you have annotated
arg1
with the type annotationUnion[str, int]
. That means it must either be astr
or anint
. It cannot be aNone
. Therefore the conditional statementif arg1 is None
is nonsensical in this context, and pyright narrows the type ofarg1
toNever
within theif
branch.In the second code snippet, pyright will do the right thing if it knows the type of
NoneExistent
. However, it has no knowledge of this type because you've imported it from a "library_without_types". Without this type knowledge, it has no way of knowing whether it derives fromstr
. It conservatively assume that it might, so theisinstance
type narrowing logic doesn't narrow the type of