While this doesn't answer the question as asked, I think you might also reconsider why you're using a TypedDict
with a string instead of a proper class to hold the enum (instead of a str
, since DisbursementType
really does seem like an enum), and which can then employ some custom serialization logic.
For example:
import dataclasses as dc
import json
from enum import Enum
class Transaction(Enum):
DISBURSEMENT = "disbursement"
REFUND = "refund"
ROLLBACK = "rollback"
def __str__(self):
return self.value
@dc.dataclass
class Disbursement:
transaction: Transaction
id_: str
amount: float
def __str__(self):
return json.dumps(dc.asdict(self), default=str)
if __name__ == "__main__":
disbursement = Disbursement(
Transaction.REFUND,
"1",
4400.24,
)
print(disbursement)
$ mypy example.py
Success: no issues found in 1 source file
$ python3 example.py
{"transaction": "refund", "id_": "1", "amount": 4400.24}
Alternatively, you can have your enum inherit from str
and simplify a few things:
import dataclasses as dc
import json
from enum import Enum
class Transaction(str, Enum):
DISBURSEMENT = "disbursement"
REFUND = "refund"
ROLLBACK = "rollback"
@dc.dataclass
class Disbursement:
transaction: Transaction
id_: str
amount: float
def __str__(self):
return json.dumps(dc.asdict(self))
if __name__ == "__main__":
disbursement = Disbursement(
Transaction.REFUND,
"1",
4400.24,
)
print(disbursement)
Other considerations:
Finally, I wanted to note that defining __str__
on my Enum did not do what I expected it to do using your TypedDict
example above; that's because str(mydict) calls repr
to provide each of mydict.values
:
class Example:
def __repr__(self):
print("I called repr!")
return "from repr"
def __str__(self):
print("I called str!")
return "from str"
if __name__ == "__main__":
print(f"example: {Example()}\n")
d = {"example": Example()}
print(f"in a dict: {d}")
$ python3 foo.py
I called str!
example: from str
I called repr!
in a dict: {'example': from repr}
Additionally, you can't add custom methods to a TypedDict
; if you change Example
to inherit from TypedDict
and rerun that last example, you'll see that neither __repr__
nor __str__
is called, and unfortunately there is no runtime error either (mypy
helpfully warns error: Invalid statement in TypedDict definition; expected "field_name: field_type"
). Because serialization logic seems to belong to Disbursement
, I changed it to a somewhat similar class that allows me to customize its __str__
: a dataclass.