Closed
Description
- Are you reporting a bug, or opening a feature request?
A question...
- Please insert below the code you are checking with mypy.
I have some union, e.g.
from typing import Union
MyUnion = Union[int, str]
and I have a function which takes the union and matches on it:
def handle_my_union(x: MyUnion) -> None:
if isinstance(x, int): ...
elif isinstance(x, str): ...
Now suppose that the union gets added a new member:
- MyUnion = Union[int, str]
+ MyUnion = Union[int, str, bytes]
I have to remember to add it to all of the places which match on the union, for example handle_my_union
. As written above, mypy doesn't warn (and has no reason to). So what I use is this function (stolen mostly verbatim from TypeScript):
from typing import NoReturn
def assert_never(x: NoReturn) -> NoReturn:
assert False, "Unhandled type: {}".format(type(x).__name__)
and use it as follows:
def handle_my_union(x: MyUnion) -> None:
if isinstance(x, int): ...
elif isinstance(x, str): ...
+ else:
+ assert_never(x)
- What is the actual behavior/output?
Now mypy warns:
error: Argument 1 to "assert_never" has incompatible type "bytes"; expected "NoReturn"
When I add a branch to handle bytes
:
def handle_my_union(x: MyUnion) -> None:
if isinstance(x, int): ...
elif isinstance(x, str): ...
+ elif isinstance(x, bytes): ...
else:
assert_never(x)
the error is gone.
- What is the behavior/output you expect?
I am happy with this solution, I just wonder if this is something that is considered appropriate to rely on, or if there's another preferable way to achieve exhaustiveness checking?
- What are the versions of mypy and Python you are using?
Python 3.5.5, mypy 0.630.
- What are the mypy flags you are using? (For example --strict-optional)
no_implicit_optional, check_untyped_defs, warn_unused_ignores
.