-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Use type(x) == T for type narrowing #10284
Changes from all commits
90ce4cd
59eefe0
c65c05a
86034c9
9e2c246
eda0d03
de398dc
5b8ef0b
5c98181
2c83c0e
275ee7a
a055d4f
aa9f345
7c37fe5
372544f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2573,3 +2573,101 @@ if issubclass(x, B): | |
else: | ||
reveal_type(x) # N: Revealed type is "Type[__main__.A]" | ||
[builtins fixtures/isinstance.pyi] | ||
|
||
[case testTypeEqualsCheck] | ||
from typing import Any | ||
|
||
y: Any | ||
if type(y) == int: | ||
reveal_type(y) # N: Revealed type is "builtins.int" | ||
|
||
|
||
[case testMultipleTypeEqualsCheck] | ||
from typing import Any | ||
|
||
x: Any | ||
y: Any | ||
if type(x) == type(y) == int: | ||
reveal_type(y) # N: Revealed type is "builtins.int" | ||
reveal_type(x) # N: Revealed type is "builtins.int" | ||
|
||
[case testTypeEqualsCheckUsingIs] | ||
from typing import Any | ||
|
||
y: Any | ||
if type(y) is int: | ||
reveal_type(y) # N: Revealed type is "builtins.int" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add also test case where you narrow from def f(x: Union[int, str]) -> None:
if type(x) is int:
reveal_type(x) # int
else:
reveal_type(x) # Union[int, str] The else block should use the original type, since instances of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I have added a test case for this and modified the type checker to handle this. Could you take a look at my changes when you get the chance? |
||
|
||
[case testTypeEqualsNarrowingUnionWithElse] | ||
from typing import Union | ||
|
||
x: Union[int, str] | ||
if type(x) is int: | ||
reveal_type(x) # N: Revealed type is "builtins.int" | ||
else: | ||
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" | ||
|
||
[case testTypeEqualsMultipleTypesShouldntNarrow] | ||
# make sure we don't do any narrowing if there are multiple types being compared | ||
|
||
from typing import Union | ||
|
||
x: Union[int, str] | ||
if type(x) == int == str: | ||
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" | ||
else: | ||
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" | ||
|
||
# mypy shows an error about "Unsupported left operand type for !=" if we don't include this | ||
[builtins fixtures/typing-medium.pyi] | ||
# mypy thinks int isn't defined unless we include this | ||
[builtins fixtures/primitives.pyi] | ||
[case testTypeNotEqualsCheck] | ||
from typing import Union | ||
|
||
x: Union[int, str] | ||
if type(x) != int: | ||
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" | ||
else: | ||
reveal_type(x) # N: Revealed type is "builtins.int" | ||
|
||
# mypy shows an error about "Unsupported left operand type for !=" if we don't include this | ||
[builtins fixtures/typing-medium.pyi] | ||
# mypy thinks int isn't defined unless we include this | ||
[builtins fixtures/primitives.pyi] | ||
|
||
[case testTypeNotEqualsCheckUsingIsNot] | ||
from typing import Union | ||
|
||
x: Union[int, str] | ||
if type(x) is not int: | ||
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" | ||
else: | ||
reveal_type(x) # N: Revealed type is "builtins.int" | ||
|
||
[case testNarrowInElseCaseIfFinal] | ||
from typing import final, Union | ||
@final | ||
class C: | ||
pass | ||
class D: | ||
pass | ||
|
||
x: Union[C, D] | ||
if type(x) is C: | ||
reveal_type(x) # N: Revealed type is "__main__.C" | ||
else: | ||
reveal_type(x) # N: Revealed type is "__main__.D" | ||
[case testNarrowInIfCaseIfFinalUsingIsNot] | ||
from typing import final, Union | ||
@final | ||
class C: | ||
pass | ||
class D: | ||
pass | ||
|
||
x: Union[C, D] | ||
if type(x) is not C: | ||
reveal_type(x) # N: Revealed type is "__main__.D" | ||
else: | ||
reveal_type(x) # N: Revealed type is "__main__.C" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: We generally use this style for documenting arguments:
This is a minor thing, however, and this doesn't block merging this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this change in #10378 because I couldn't figure out how to add more commits to this branch after it's already been merged.