-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Support narrowing Union of List types via index and isinstance #9362
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
Comments
This is a special case in mypy. If you rewrite the initialization like this it works:
Honestly I don't think this is documented very well -- you might be able to infer this from Explicit types for variables but it could be more explicit. |
I think I may have made my example too simple. In my current use case I parse some data from a network response which is a union of two different list types: I'm hoping to refine this response via indexing and an from typing import Union, List
from dataclasses import dataclass
@dataclass
class SearchResult:
id: str
score: float
match: str
def get_search_results() -> Union[List[List[str]], List[SearchResult]]:
...
x = get_search_results()
if isinstance(x[0], SearchResult):
reveal_type(x)
# expected: builtins.list[main.SearchResult]
# actual: Union[builtins.list[builtins.list[builtins.str]], builtins.list[main.SearchResult]]
else:
reveal_type(x)
# expected: builtins.list[builtins.str]
# actual: Union[builtins.list[builtins.list[builtins.str]], builtins.list[main.SearchResult]] which I think can be simplified to the following as a test case from typing import Union, List
def foo() -> Union[List[str], List[int]]:
...
x = foo()
if isinstance(x[0], str):
reveal_type(x)
# expected: builtins.list[builtins.str]
# actual: Union[builtins.list[builtins.str], builtins.list[builtins.int]]
else:
reveal_type(x)
# expected: builtins.list[builtins.int]
# actual: Union[builtins.list[builtins.str], builtins.list[builtins.int]] |
Ah, okay. I think this is a feature request. |
Allows for narrowing a union of list types by indexing into the list and checking the type of an element. mypy already narrows the specific index expression. Since mypy already narrows the index expression's type, we use the type to compare against the type arguments of the lists and generate a new type that is narrower than the original. ``` from typing import Union, List a: Union[List[List[int]], List[int]] # before if isinstance(a[0], list): reveal_type(a) # N: Revealed type is 'Union[builtins.list[builtins.list[builtins.int]], builtins.list[builtins.int]]' else: reveal_type(a) # N: Revealed type is 'Union[builtins.list[builtins.list[builtins.int]], builtins.list[builtins.int]]' # after if isinstance(a[0], list): reveal_type(a) # N: Revealed type is 'builtins.list[builtins.list[builtins.int]]' else: reveal_type(a) # N: Revealed type is 'builtins.list[builtins.int]' ``` fixes: python#9362
It would be nice to be able to narrow a union of two different list types via indexing into the array and using an
isinstance
checkOne caveat is that the array could be empty, but let's assume we make an emptiness check before indexing
The text was updated successfully, but these errors were encountered: