Skip to content

Narrow Union[str, Literal[False]] via is #8810

Closed
@sbdchd

Description

@sbdchd

With the Union[str, Literal[False]] type below, mypy narrows the type correctly via isinstance, but is not False and is False do not work as expected.

from typing import Union, Literal

x: Union[str, Literal[False]] = False

if x is not False:
    reveal_type(x) # note: Revealed type is 'Union[builtins.str, Literal[False]]'
    
assert x is not False
reveal_type(x) # note: Revealed type is 'Union[builtins.str, Literal[False]]'

assert x is False
reveal_type(x) # note: Revealed type is 'Union[builtins.str, Literal[False]]'

assert not isinstance(x, bool)
reveal_type(x) # note: Revealed type is 'builtins.str'

Expected:

is not False and is False to narrow Union[str, Literal[False]]

Actual:

type isn't narrowed

mypy version: 0.770

test case

diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test
index 45d4a625..4b693165 100644
--- a/test-data/unit/check-narrowing.test
+++ b/test-data/unit/check-narrowing.test
@@ -984,3 +984,20 @@ if true_or_false:
 else:
     reveal_type(true_or_false)  # N: Revealed type is 'Literal[False]'
 [builtins fixtures/primitives.pyi]
+
+[case testNarrowingLiteralIdentityCheck]
+from typing import Union
+from typing_extensions import Literal
+
+str_or_false: Union[Literal[False], str]
+
+if str_or_false is not False:
+    reveal_type(str_or_false)   # N: Revealed type is 'builtins.str'
+else:
+    reveal_type(str_or_false)   # N: Revealed type is 'Literal[False]'
+
+if str_or_false is False:
+    reveal_type(str_or_false)  # N: Revealed type is 'Literal[False]'
+else:
+    reveal_type(str_or_false)  # N: Revealed type is 'builtins.str'
+[builtins fixtures/primitives.pyi]

semi related:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions