I don’t know if it’s been brought up before, but I wonder why is this not currently allowed:
@overload
def foo(a: A1) -> B1:
...
@overload
def foo(a: A2) -> B2:
...
def foo(a):
# actual code here
If given no type hints, the type of foo should be the union of its overloads.
Currently, you allowed to write something like this if you add # type: ignore on the real function, but I have no real idea if the type checker deal with this as well as I’d hope.
When I tried this I got no error from mypy nor from pyright (via VS Code + PyLance). Could you tell us what tool you are using for type checking and what error you got?
OK, I figured it out, this happens because my project uses --strict which enables --disallow-untyped-defs.
I still wonder if it’s right for these checking modes to behave like that when all overloads are typed, though.
But perhaps I should close this topic, as it is clearly mypy-specific behavior.
I personally found typing.overloads unintuitive when I first came across it, I came to realize it’s for specifying an interface for code that is calling the respective function and is not used to check code in the function. Hence why mypy complains (in strict mode) when you don’t specify types in the function signature, because no type checking is being done inside the function for these variables.
I would find overload a lot more useful if there were an option to have the type checker check each overload actually works for the code in the function.
But from my memory of first discovering this and getting confused and going to read various mypy GitHub issues it is currently considered complex to implement and no one has proposed a solution or standard.