-
-
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
Incorrect type narrowing on union of TypedDict
#12098
Comments
I'm adding mypy to a project just now and it left me wanting a bit around nested TypedDicts. and I think my issue is connected to this one. from typing import TypedDict, Union
class InnerA(TypedDict):
common_key: str
class InnerB(TypedDict):
common_key: str
extra_key: int
class Outer(TypedDict):
id: int
inner: list[Union[InnerA, InnerB]]
my_outer: Outer = {
'id': 1,
'inner': [{
'common_key': 'which type could it be?',
'extra_key': 2
}]
} This trips up mypy, which then complains that |
Maybe you have a usecase in your code that actually requires it, but that example could just use a single TypedDict with an optional extra_key. |
from typing import Union, TypedDict, cast
class DictA(TypedDict):
a: str
class DictAAndB(TypedDict):
a: str
b: str
class DictC(TypedDict):
c: str
def func(foo: Union[DictA, DictAAndB, DictC, None]) -> None:
reveal_type(foo)
# Mypy:
# Union[
# TypedDict('test_mypy.DictA', {'a': builtins.str}),
# TypedDict('test_mypy.DictAAndB', {'a': builtins.str, 'b': builtins.str}),
# TypedDict('test_mypy.DictC', {'c': builtins.str}),
# None,
# ]
# Pyright:
# DictA | DictAAndB | DictC | None
#
# Expected.
assert foo is not None
reveal_type(foo)
# Mypy:
# Union[
# TypedDict('test_mypy.DictA', {'a': builtins.str}),
# TypedDict('test_mypy.DictC', {'c': builtins.str}),
# ]
# Pyright:
# DictA | DictAAndB | DictC
#
# Unexpected behavior from Mypy only. What happened to DictAAndB?
foo = cast(Union[DictA, DictAAndB, DictC], foo)
reveal_type(foo)
# Mypy:
# Union[
# TypedDict('test_mypy.DictA', {'a': builtins.str}),
# TypedDict('test_mypy.DictC', {'c': builtins.str}),
# ]
# Pyright:
# DictA | DictAAndB | DictC
#
# Is there any workaround? I think this is caused by the same underlying behavior as the OP. Mypy 1.11.1. Pyright narrows the types in exactly the way I expect. |
Continuing to try to work around this; it seems I can't even |
I ended up switching to Pyright for this project because I couldn't find any way to override Mypy's incorrect narrowing in this situation. |
Mypy doesn't work here because of a bug that can't be worked around: <python/mypy#12098 (comment)>
Mypy doesn't work here because of a bug that can't be worked around: <python/mypy#12098 (comment)>
I also get the same result if I make it
not data
. The_SessionData
type just disappears for no reason and it keeps saying the empty dict will be the result regardless of the boolean check.The text was updated successfully, but these errors were encountered: