I am trying to create a TypedDict
for better code completion and am running into an issue.
I want to have a fixed set of keys (an Enum) and the values to match a specific list of objects depending on the key.
For example:
from enum import Enum
class OneObject:
pass
class TwoObject:
pass
class MyEnum(Enum):
ONE: 1
TWO: 2
I am looking to have something like this:
from typing import TypedDict
class CustomDict(TypedDict):
MyEnum.ONE: list[OneObject]
MyEnum.TWO: list[TwoObject]
However, I am getting Non-self attribute could not be type hinted
and it doesn't really work. What are my options?
This is not compatible with the TypedDict
specification as laid out in PEP 589. Let me quote: (emphasis mine)
A TypedDict type represents dictionary objects with a specific set of string keys, and with specific value types for each valid key.
So using arbitrary enum members for defining TypedDict
keys is invalid.
While TypedDict
does also support an alternative, functional definition syntax and you could theoretically make your enum have the str
data type by doing class MyEnum(str, Enum): ...
, you would still probably not be able to define a TypedDict
with those enum members in a way that your type checker understands.
That is because only actual string literals are officially accepted as keys as mentioned in the section on the Use of Final Values and Literal Types. Quote: (again, emphasis mine)
Type checkers are only expected to support actual string literals, not final names or literal types, for specifying keys in a TypedDict type definition. [...] The motivation for this is to make type declarations self-contained, and to simplify the implementation of type checkers.
In other words, whether something like the following is supported depends entirely on any given type checker:
from enum import Enum
from typing import TypedDict
class OneObject:
pass
class TwoObject:
pass
class MyEnum(str, Enum):
ONE = "1"
TWO = "2"
CustomDict = TypedDict(
"CustomDict",
{MyEnum.ONE: list[OneObject], MyEnum.TWO: list[TwoObject]}
)
Mypy (currently) does not and gives the output: error: Invalid TypedDict() field name
. (By the way, I tested it with Final
variables as keys and those are also rejected.)
So depending on what your use case is, you will probably have to bite the bullet and explicitly type out the enum/key names again or just not use an enum for that in the first place, as suggested by @artem in his answer.