Search code examples
pythonpython-typing

How to make generic proxy types work with static type checkers


I'm writing an ORM wrapper that allows one to write model definitions with type annotations. I would now like to add generic types Unique[T], Index[T] and Primary[T] to annotate types that have a corresponding constraint. However, I would like those types to be transparent proxies for T for IDEs and other static type checkers. So if one has a type like:

something: Unique[str]

Type checkers and IDEs would act like it said:

something: str

The current implementation is:

T = TypeVar('T')
class Unique(Generic[T]):
    def __new__(cls, *args, **kwargs):
        raise TypeError(f'cannot instantiate {cls}')

Would there be a way to make it into a sort of proxy type?


Solution

  • To the best of my knowledge, there is no PEP 484-compliant way of doing this.

    It may, however, be possible to write a plugin to support this use case if you're using specifically mypy. The only downside is that the plugin system is still very new and in flux and so is intentionally poorly documented -- if you want to try using it, you should be prepared to do a bit of digging.

    If, however, you want to apply your 'Unique', 'Index', and 'Primary' constraints to only a fixed number of types, you could perhaps use NewType, like so:

    from typing import NewType
    
    UniqueInt = NewType('UniqueInt', int)
    UniqueStr = NewType('UniqueStr', str)
    # etc...
    

    This is a bit hacky, but it does let you create distinct subclasses of existing concrete types, which can let you get the proxying effect.