- 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.
A question...
I have some union, e.g.
and I have a function which takes the union and matches on it:
Now suppose that the union gets added a new member:
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):and use it as follows:
def handle_my_union(x: MyUnion) -> None: if isinstance(x, int): ... elif isinstance(x, str): ... + else: + assert_never(x)Now mypy warns:
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.
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?
Python 3.5.5, mypy 0.630.
no_implicit_optional, check_untyped_defs, warn_unused_ignores.