diff --git a/simple_value_object/value_object.py b/simple_value_object/value_object.py index 5a207dc..a21c839 100644 --- a/simple_value_object/value_object.py +++ b/simple_value_object/value_object.py @@ -13,6 +13,7 @@ def __init_subclass__(cls): cls = dataclass(cls) def __post_init__(self): + self.__check_annotations() self.__replace_mutable_fields_with_immutable() self.__check_invariants() @@ -39,6 +40,15 @@ def __get_mutable_fields(self): self.__dataclass_fields__.values(), ) + def __check_annotations(self): + for field in self.__dataclass_fields__.values(): + if not isinstance( + getattr(self, field.name), self.__annotations__[field.name] + ): + raise TypeError( + f"{field.name} must be of type {self.__annotations__[field.name]}" + ) + def __check_invariants(self): for invariant in self.__obtain_invariants(): if self.__is_invariant_violated(invariant): diff --git a/specs/value_object_spec.py b/specs/value_object_spec.py index 332d19e..60de3e8 100644 --- a/specs/value_object_spec.py +++ b/specs/value_object_spec.py @@ -252,3 +252,22 @@ def first_year_quarter(self): return 0 expect(lambda: Date(8, 6, 2002)).to(raise_error(InvariantMustReturnBool)) + + with context("ensures that defined data types are respected"): + + with it("raises an exception when a field is not the expected type"): + expect(lambda: Point("5", 3)).to( + raise_error(TypeError, "x must be of type ") + ) + expect(lambda: Point(5, "3")).to( + raise_error(TypeError, "y must be of type ") + ) + with it( + "raises an exception when a inner value object is not the expected type" + ): + expect(lambda: Money(Decimal("100"), "€")).to( + raise_error( + TypeError, + "currency must be of type ", + ) + )