Reputation: 164
I'm trying to make a TypedDict
subclass that returns None
if a key would cause a KeyError
and that key is a part of the TypedDict
's annotations as Optional
. I realize this isn't quite possible, since TypedDict
can't be subclassed except to define annotations. Is there any other eloquent way to do this?
Here's what I'm trying to do:
from typing import TypedDict, get_args, get_origin
class FilledTypedDict(TypedDict):
def __getitem__(self, k):
if k in self.__annotations__:
annotation = self.__annotations__[k]
if get_origin(annotation) is Union and type(None) in get_args(annotation):
return None
return super().__getitem__(k)
This gives me a TypedDict classes can contain only type annotations
. How do I work my way around that?
Upvotes: 3
Views: 1987
Reputation: 50126
You do not. TypedDict
is not a proper type, it is a representation of a regular dict
with well-defined items.
The entire point is that there are no instances of TypedDict
and any dict
with correct items can be assigned to a TypedDict
variable.
from typing import TypedDict
class TD(TypedDict):
a: int
b: str
print(type(TD(a=1, b="two"))) # <class 'dict'>
td: TD = {"a": 1, "b": "two"} # valid
This makes it impossible to add behaviour to a TypedDict
, since it must always match the dict
behaviour exactly.
PEP 589 –– TypedDict - Methods are not allowed, since the runtime type of a TypedDict object will always be just
dict
(it is never a subclass ofdict
).
What can be done is to satisfy the "TypedDict
with Optional
values" type – by explicitly setting missing values to None
.
from typing import Optional, TypedDict
class Call(TypedDict):
who: str
when: Optional[str]
call: Call
call = Call(who="Gwen", when="tomorrow") # valid
call = {"who": "me", "when": None} # valid
call = {"who": "us"} # error: Missing key 'when' for TypedDict "Call"
Upvotes: 2