Search code examples
pythontypestype-hinting

Giving Union of types as `bound` argument of TypeVar and calling overloaded function that requires one of the types, type checker reports an error


Checking the following code with mypy, it says 30: error: Argument 1 to "f" has incompatible type "T"; expected "X".

But there are decorated declarations of f so we should be able to pass value of class X or Y as the argument a.

Question 1: Could not we use @overload and TypeVar(bound=Union) at the same time ? Or I misunderstand something ?

from typing import TypeVar, Union, overload


class X:
    pass


class Y:
    pass


@overload
def f(a: X):
    ...


@overload
def f(a: Y):
    ...


def f(a):
    return


T = TypeVar("T", bound=Union[X, Y])


def func(a: T) -> T:
    f(a)
    return a

I tried another example as following and it does not make type errors.

Question 2: What makes the difference between overloaded function and classes having same method ?

from typing import TypeVar, Union


class X:
    def method(self) -> float:
        return 1.0


class Y:
    def method(self) -> float:
        return 1.0


T = TypeVar("T", bound=Union[X, Y])


def func(a: T) -> T:
    a.method()
    return a

Solution

  • Question 1: Could not we use @overload and TypeVar(bound=Union) at the same time ? Or I misunderstand something ?

    The problem is with TypeVar: what you want is T = TypeVar("T", X, Y) because both X and Y should be accepted. See the usage paragraph in the documentation. The bound parameter is used only if you want to define an upper bound to the types, basically you are specifying the constraining superclass. For more details, see Type variables with an upper bound.

    Question 2: What makes the difference between overloaded function and classes having same method ?

    The @overload decorator is useful in case there are two functions/methods sharing the same scope, in fact

    The variants and the implementations must be adjacent in the code: think of them as one indivisible unit.

    Source