Title: Preferred idiom for exhaustiveness checking of unions · Issue #5818 · python/mypy · GitHub
Open Graph Title: Preferred idiom for exhaustiveness checking of unions · Issue #5818 · python/mypy
X Title: Preferred idiom for exhaustiveness checking of unions · Issue #5818 · python/mypy
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 th...
Open Graph 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, s...
X 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, s...
Opengraph URL: https://github.com/python/mypy/issues/5818
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Preferred idiom for exhaustiveness checking of unions","articleBody":"* Are you reporting a bug, or opening a feature request?\r\n\r\nA question...\r\n\r\n* Please insert below the code you are checking with mypy.\r\n\r\nI have some union, e.g.\r\n\r\n```python\r\nfrom typing import Union\r\n\r\nMyUnion = Union[int, str]\r\n```\r\n\r\nand I have a function which takes the union and matches on it:\r\n\r\n```python\r\ndef handle_my_union(x: MyUnion) -\u003e None:\r\n if isinstance(x, int): ...\r\n elif isinstance(x, str): ...\r\n```\r\n\r\nNow suppose that the union gets added a new member:\r\n\r\n```diff\r\n- MyUnion = Union[int, str]\r\n+ MyUnion = Union[int, str, bytes]\r\n```\r\n\r\nI 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](https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking)):\r\n\r\n```python\r\nfrom typing import NoReturn\r\n\r\ndef assert_never(x: NoReturn) -\u003e NoReturn:\r\n assert False, \"Unhandled type: {}\".format(type(x).__name__)\r\n```\r\n\r\nand use it as follows:\r\n\r\n```diff\r\n def handle_my_union(x: MyUnion) -\u003e None:\r\n if isinstance(x, int): ...\r\n elif isinstance(x, str): ...\r\n+ else:\r\n+ assert_never(x)\r\n```\r\n\r\n* What is the actual behavior/output?\r\n\r\nNow mypy warns:\r\n\r\n```\r\nerror: Argument 1 to \"assert_never\" has incompatible type \"bytes\"; expected \"NoReturn\"\r\n```\r\n\r\nWhen I add a branch to handle `bytes`:\r\n\r\n```diff\r\n def handle_my_union(x: MyUnion) -\u003e None:\r\n if isinstance(x, int): ...\r\n elif isinstance(x, str): ...\r\n+ elif isinstance(x, bytes): ...\r\n else:\r\n assert_never(x)\r\n```\r\n\r\nthe error is gone.\r\n\r\n* What is the behavior/output you expect?\r\n\r\nI 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?\r\n\r\n* What are the versions of mypy and Python you are using?\r\n\r\nPython 3.5.5, mypy 0.630.\r\n\r\n* What are the mypy flags you are using? (For example --strict-optional)\r\n\r\n`no_implicit_optional, check_untyped_defs, warn_unused_ignores`.\r\n","author":{"url":"https://github.com/bluetech","@type":"Person","name":"bluetech"},"datePublished":"2018-10-22T09:30:12.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":21},"url":"https://github.com/5818/mypy/issues/5818"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:97e9845f-8a2f-1b39-2c2c-dd6c5ef1c39c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E930:CB088:4A5BD5:6C1340:6A574C6B |
| html-safe-nonce | 6bfd8676d6f61daa72c8f07a35c92edd158bc7e10ab7ed89bcad1a6b80e4a2d8 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFOTMwOkNCMDg4OjRBNUJENTo2QzEzNDA6NkE1NzRDNkIiLCJ2aXNpdG9yX2lkIjoiODAwNTc4MzI2NDQ1MDUzMDQxMiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 768d248cda6d77433db7c0546952582a7e9a73e981d063c6f09e07d3cb25aa20 |
| hovercard-subject-tag | issue:372451340 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/mypy/5818/issue_layout |
| twitter:image | https://opengraph.githubassets.com/50c605ac742b03ecad626a6df9a1f62972f0cab0c9b31bb573dc3d40903c702f/python/mypy/issues/5818 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/50c605ac742b03ecad626a6df9a1f62972f0cab0c9b31bb573dc3d40903c702f/python/mypy/issues/5818 |
| og:image:alt | 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, s... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | bluetech |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4e7a7296a3830877cf21a6ad2a972c9e618a48915e03966cf0c53eb08e5aad98 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/mypy git https://github.com/python/mypy.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 7053637 |
| octolytics-dimension-repository_nwo | python/mypy |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 7053637 |
| octolytics-dimension-repository_network_root_nwo | python/mypy |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 602250ea3b6dd8302a7220ef98adb828dbc807e4 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width