-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Description
Python 3.7.4, typing_extensions 3.7.4, mypy 0.720
I'm trying to use Literal
and @overload
to change the result type of a function depending on a boolean switch.
This issue is not specific to Literal, but it makes it easier to produce an easy to understand real-life use case.
Everything works great as long as the parameter is mandatory:
from typing import overload, Optional
from typing_extensions import Literal
@overload
def plusone(x: Optional[int], none_to_zero: Literal[True]) -> int:
...
@overload
def plusone(x: Optional[int], none_to_zero: Literal[False]) -> Optional[int]:
...
def plusone(x, none_to_zero):
if x is None:
if none_to_zero:
x = 0
else:
return None
return x + 1
plusone(None, True).to_bytes(4, "little") # ok
plusone(None, False).to_bytes(4, "little") # not ok
mypy output: 25: error: Item "None" of "Optional[int]" has no attribute "to_bytes"
However, if I set a default value:
from typing import overload, Optional
from typing_extensions import Literal
@overload
def plusone(x: Optional[int], none_to_zero: Literal[True] = True) -> int:
...
@overload
def plusone(x: Optional[int], none_to_zero: Literal[False] = True) -> Optional[int]:
...
def plusone(x, none_to_zero=True):
if x is None:
if none_to_zero:
x = 0
else:
return None
return x + 1
plusone(None, True).to_bytes(4, "little") # ok
plusone(None, False).to_bytes(4, "little") # not ok
plusone(None).to_bytes(4, "little") # ok
mypy output:
11: error: Incompatible default for argument "none_to_zero" (default has type "Literal[True]", argument has type "Literal[False]")
25: error: Item "None" of "Optional[int]" has no attribute "to_bytes"
Workaround
Add # type: ignore
on line 11. The error on line 25 is still reported.
Expected behaviour
In each of the signatures of an @overload
'ed function, the allowed default values of an optional parameter should be the Union of type annotations from all the signatures.
Metadata
Metadata
Assignees
Labels
No labels