def typed_property(name, expected_type):
    """
    Example 1:
    class Person:
        name = typed_property('name', str)
        age = typed_property('age', int)

    Example 2:
    String = partial(typed_property, expected_type=str)
    Integer = partial(typed_property, expected_type=int)
    class Person:
        name = String('name')
        age = Integer('age')

    :param name:
    :param expected_type:
    :return:
    """
    storage_name = '_' + name

    @property
    def prop(self):
        return getattr(self, storage_name)

    @prop.setter
    def prop(self, value):
        if not isinstance(value, expected_type):
            raise TypeError('{} must be a {}'.format(name, expected_type))
        setattr(self, storage_name, value)

    return prop