from typing import Any


def typedproperty(name: str, expected_type: Any) -> Any:
    """
    Creates property setter and getter allowing for data type control.

    Args:
        name: String - name of the property.
        expected_type: Any - expected type of the property.
    Raises:
        TypeError: When value supplied to setter doesn't match expected type.

    Usage:

    import typedproperty as tp

    class Stock:

        name = tp.String('name')
        shares = tp.Integer('shares')
        price = tp.Float('price')

        def __init__(self, name: str, shares: int, price: float) -> None:
            self.name = name
            self.shares = shares
            self.price = price

        ...
    """

    private_name = '_' + name

    @property
    def prop(self) -> Any:
        return getattr(self, private_name)

    @prop.setter
    def prop(self, value: Any) -> None:
        if not isinstance(value, expected_type):
            raise TypeError(f"Expected {expected_type}")
        setattr(self, private_name, value)

    return prop