I'm trying to remove the Any type hint from code similar to the following:
from typing import TypedDict, Any
class NestedDict(TypedDict):
foo: str
class EventDict(TypedDict):
nested: NestedDict
class BaseEventDict(TypedDict):
nested: Any # this should accept NestedDict but also other TypedDicts which may contain additional fields
test_dict: EventDict = {
"nested": {"foo": "abc"},
}
def print_dict(source_dict: BaseEventDict):
print(source_dict)
print_dict(test_dict)
Since the nested field can contain either NestedDict or other TypedDicts with additional fields (for other EventDicts), I've not been able to come up with a compatible TypedDict (mypy complains about extra keys). I thought Mapping[str, object] might work in Any's place, since [A]ny TypedDict type is consistent with Mapping[str, object]. However, mypy complains with Argument 1 to "print_dict" has incompatible type "EventDict"; expected "BaseDict". Is there anything I can use instead of Any, which essentially disables the check? Also, any insights into why Mapping[str, object] is not a valid type here?
TypedDictfields are invariant, becauseTypedDictis a mutable structure. The reasoning behind that is explained in PEP589 in detail. So, to accept aTypedDictwith a field of type "someTypedDictor anything compatible with it" you can use a generic solution:BaseEventDictis parametrized with a type of its field, which is bound toNestedDict- this wayTcan be substituted only with something compatible withNestedDict. Let's check:In this setup
print_dictis also interesting: you cannot use an upper bound, because the field type is invariant, so a singleTypeVarwith a bound (same as before) comes to rescue. Anything compatible withNestedDictis accepted as_Tresolver, and everything incompatible is rejected.Here's a playground with this implementation.