Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support typing.Union/typing.Optional in isinstance check (/support old-style unions) #17680

Open
bram-tv opened this issue Aug 15, 2024 · 1 comment
Labels

Comments

@bram-tv
Copy link

bram-tv commented Aug 15, 2024

Preamble

Feature

Example code

from typing import Any, Union, Optional

foo: Any = None

if isinstance(foo, int | None):
    reveal_type(foo)

if isinstance(foo, Union[int, None]):
    reveal_type(foo)

if isinstance(foo, Optional[int]):
    reveal_type(foo)

bar = int | None
baz = Optional[int]
if isinstance(foo, bar):
    reveal_type(foo)

if isinstance(foo, baz):
    reveal_type(foo)

Output for the above with mypy v1.11.1:

src/union.py:6: note: Revealed type is "Union[builtins.int, None]"
src/union.py:8: error: Argument 2 to "isinstance" has incompatible type "<typing special form>"; expected "_ClassInfo"  [arg-type]
src/union.py:9: note: Revealed type is "Any"
src/union.py:11: error: Argument 2 to "isinstance" has incompatible type "<typing special form>"; expected "_ClassInfo"  [arg-type]
src/union.py:12: note: Revealed type is "Any"
src/union.py:17: note: Revealed type is "Union[builtins.int, None]"
src/union.py:19: error: Parameterized generics cannot be used with class or instance checks  [misc]
src/union.py:19: error: Argument 2 to "isinstance" has incompatible type "<typing special form>"; expected "_ClassInfo"  [arg-type]
src/union.py:20: note: Revealed type is "Any"
Found 4 errors in 1 file (checked 1 source file)

Running the above with pyright:

.../src/union.py
  .../src/union.py:6:17 - information: Type of "foo" is "int | None"
  .../src/union.py:9:17 - information: Type of "foo" is "int | None"
  .../src/union.py:12:17 - information: Type of "foo" is "int | None"
  .../src/union.py:17:17 - information: Type of "foo" is "int | None"
  .../src/union.py:20:17 - information: Type of "foo" is "int | None"
0 errors, 0 warnings, 5 informations

Summary:

  • when using the PEP 604-syntax the type is correctly narrowed to Union[builtins.int, None]
  • when using the typing.Union and/or typing.Optional syntax the type is not narrowed and remains Any (and errors are shown)
@hauntsaninja
Copy link
Collaborator

PR welcome. IIRC isinstance on old-style unions is only supported on 3.10 and newer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants