Making TypedDict work with keys of other types like StrEnum would require a change to the TypedDict specification [this pyright comment]
from enum import StrEnum
from typing import Final, TypedDict
A = 'a'
class Foo(StrEnum):
a = 'a'
class Bar(TypedDict):
a: int
bar: Bar = {A: 1} # Ok
bar2: Bar = {Foo.a: 1} # Error: Expression of type "dict[Foo, int]" cannot be assigned to declared type "Bar"
bar3: Final[Bar] = {Foo.a: 1} # As above
bar[Foo.a] # Error: Could not access item in TypedDict; "Literal[Foo.a]" is not a string literal
Maybe the example is overly contrived (taken from the pyright issue).
For us this has arisen naturally when we have converted untyped dicts to typed dicts. The existing code often used a string enum to keep track of valid keys and thus have many instances of data_dict[Keys.key_1]. You could argue that it would be best to replace the Keys.key_1 usages by the literal string after the conversion, but I’m not fully convinced that has much value by itself.
Retiring the Keys enum does remove the need to keep the typed dict and enum in sync, but sometimes the keys are used outside a direct typed dict context. (Eg.: a function which expects a key which later is used to index the typed dict).
Besides “is it bad practice to use string enums to index typed dicts”, I’m struggling to understand the rationale for not allowing this. String enum values surely are intended to be final (even if it might technically be possible to mutate them runtime).
Quoting “layday” from the pyright issue:
… StrEnum’s raison d’etre is to avoid having to access value
I can’t reproduce the first one passing. TypedDicts are supposed to be defined with string literals. … Which typechecker are you using?
pyright. It claims A is a Literal[‘a’] though. (I miiight have some settings on which affect this )