Search code examples
pythonpython-3.xfactorytype-hintingtyping

How to type hint a return value that's defined in the function's local scope?


Given the following example:

class A:
    def __init__(self, num: int):
        self.num = num

    def bar(self, eggs: int):
        if eggs == self.num:
            raise ValueError


def foo(spam: bool) -> B:
    class B(A):
        def bar(self, eggs: int):
            try:
                super().bar(eggs)
            except ValueError as e:
                if not spam:
                    raise e
    return B

The base class A has a method named bar that raises a ValueError if eggs equals to self.num. I also have a function named foo that accepts an argument spam, it returns a subclass of A and overrides the bar method so that no ValueError will be raised if spam is non Falsey.

I'm trying to type hint the return value for the foo function. If I do -> B, B is undefined. If I do -> A, type B isn't exactly A. If I do -> "B", using future hinting, B is still not defined since it's in a local scope.

Is there anyway to type hint this? If not, is there a better way to rewrite my code?


Solution

  • Here's what I could think of from a quick scan of the docs. This isn't a good solution at all (I think), but it should do the job for you.

    There's something called typing.TypeVar (docs). Its basically a generic type. So what you could possibly do is:

    At the global level (after defining class A) define:

    from typing import TypeVar
    B = TypeVar('B', bound=A)
    

    Now in the function signature of def foo you can say:

    def foo(spam: bool) -> B:
    

    Then inside the function you can continue to create a new class with the name B and return it.

    I'm not even sure if this would work properly in all cases. If you find any problems with it, definitely correct me and post here.