Description
- Are you reporting a bug, or opening a feature request? Bug
- Please insert below the code you are checking with mypy:
from typing import Optional
def bar(var: str):
pass
def foo(var: Optional[str]=None):
var_not_None = not (var is None)
if var_not_None:
# var can only be a `str` at this point,
# but `mypy` complains that
# Argument 1 to "bar" has incompatible type "Optional[str]"; expected "str"
bar(var)
def foo2(var: Optional[str]=None):
if not(var is None):
# no complaints from mypy
bar(var)
- What is the actual behavior/output?
Running mypy
on this reproducer returns:
error: Argument 1 to "bar" has incompatible type "Optional[str]"; expected "str" Found 1 error in 1 file (checked 1 source file)
- What is the behavior/output you expect?
No errors, both foo2
and foo
are equivalent.
- What are the versions of mypy and Python you are using?
mypy 0.782
and Python 3.6.8
- Do you see the same issue after installing mypy from Git master?
Yup, unless I did something wrong 😅
Summary:
When you have an Optional[str]
-typed variable var
, one would expect that an not (var is None)
check in an if-statement
should tell mypy
that all code within that branch has that the variable has type str
. Indeed, mypy
shows the expected behaviour for this, as shown in function foo2
above.
However, there are many instances where you want to check if a variable is None
outside of the if-statement. For instance, if your if-statement were to check many boolean conditions at once. In this situation, one may save the result of the check into a variable. This is the case in the foo
function above, where mypy
complains.
I suspect this problem may not be solvable in the general case, but perhaps we can improve the status-quo nonetheless to catch this error.
If this is a beginner-friendly bug, I would love to help fix it! I've been meaning to get involved with the mypy
project; just some guidance would do. Thanks!