Dataclass With Post-Init Validation

Validate invariants in a dataclass post-init hook so invalid instances cannot be constructed, keeping bad data out of the rest of the system.

PythonData Integrity

Code

snippet
from dataclasses import dataclass, field


@dataclass(frozen=True)
class Money:
    amount: int
    currency: str = "USD"

    def __post_init__(self) -> None:
        if not isinstance(self.amount, int):
            raise TypeError("amount must be an int number of minor units")
        if self.amount < 0:
            raise ValueError("amount must be non-negative")
        if self.currency not in {"USD", "EUR", "GBP"}:
            raise ValueError(f"unsupported currency: {self.currency}")

    def add(self, other: "Money") -> "Money":
        if other.currency != self.currency:
            raise ValueError("cannot add different currencies")
        return Money(self.amount + other.amount, self.currency)