PEP 647 introduced type guards to perform complex type narrowing operations using functions. If I have a class where properties can have various types, is there a way that I can perform a similar type narrowing operation on the property of an object given as the function argument?
class MyClass:
"""
If `a` is `None` then `b` is `str`
"""
a: Optional[int]
b: Optional[str]
# Some other things
def someTypeGuard(my_obj: MyClass) -> ???:
return my_obj.a is not None
I'm thinking it might be necessary for me to implement something to do with square brackets in type hints, but I really don't know where to start on this.
TypeGuard
annotations can be used to annotate subclasses of a class. If parameter types are specified for those classes, then MyPy will recognise the type narrowing operation successfully.
class MyClass:
a: Optional[int]
b: Optional[str]
# Some other things
# Two hidden classes for the different types
class _MyClassInt(MyClass):
a: int
b: None
class _MyClassStr(MyClass):
a: None
b: str
def my_class_has_a(my_obj: MyClass) -> TypeGuard[_MyClassInt]:
"""Check if my_obj's `a` property is NOT `None`"""
return my_obj.a is not None
def my_class_has_b(my_obj: MyClass) -> TypeGuard[_MyClassStr]:
"""Check if my_obj's `b` property is NOT `None`"""
return my_obj.b is not None
Sadly failure to narrow to one type doesn't automatically narrow to the other type, and I can't find an easy way to do this other than an assert my_class_has_b(obj)
in your else block.
Even still this seems to be the best solution.