Allowing type hints only on typing.overloads, with an untyped function/method implementation

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?

Here’s what I tried in the mypy playground:

That is strange. I get a no-untyped-def on my mbp laptop using the example code from the mypy playground.

The playground version doesn’t do that, even if I make it use the same mypy version (0.991).

$ python -V
Python 3.10.10
$ mypy --version
mypy 0.991 (compiled: yes)
$ mypy 222.py
222.py:16: error: Function is missing a type annotation  [no-untyped-def]
Found 1 error in 1 file (checked 1 source file)
$ cat 222.py
from typing import overload

class A1: ...
class B1: ...
class A2: ...
class B2: ...

@overload
def foo(a: A1) -> B1:
    ...

@overload
def foo(a: A2) -> B2:
    ...

def foo(a):
   # actual code here
   ...

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.

1 Like