Using a property as type guard

I have some properties on a class telling me if the instance is of the right type.
For example:

class Object:
    @property
    def is_module(self):
        return isinstance(self, Module)

    @property
    def is_class(self):
        return isinstance(self, Class)

class Module(Object): ...

class Class(Object): ...

I would like to annotate these properties as type guards, but it does not seem to be supported by the specification (PEP 647):

    @property
    def is_module(self) -> TypeGuard[Module]:
        return isinstance(self, Module)

…gives error: TypeGuard functions must have a positional argument [valid-type].

PEP 647 says this:

A concern was raised that there may be cases where it is desired to apply the narrowing logic on self and cls. This is an unusual use case, and accommodating it would significantly complicate the implementation of user-defined type guards. It was therefore decided that no special provision would be made for it. If narrowing of self or cls is required, the value can be passed as an explicit argument to a type guard function.

Is there any other way :slight_smile: ?

1 Like

I don’t think there is another way :confused:

It’s funny that the only times I have wanted to use TypeGuard was when I wanted to narrow self, so I don’t think it’s as unusual as the PEP makes it sound.

4 Likes

Yup, I keep coming back to this. I almost never use TypeGuard, and the only times I want to use it is when I add a convenient property to a class to avoid having to use isinstance (and therefore having to import an additional class at runtime) :sweat_smile: