Assume a function like:
def get_item(key: str, default: Optional[Item] = None) -> Optional[Item]:
# implementation goes here
...
Now let's assume we want to enhance typing through an @overload by changing it to:
@overload
def get_item(key: str) -> Item:
...
def get_item(key: str, default: Optional[Item] = None) -> Optional[Item]:
# implementation goes here
...
mypy will complain with:
error: Single overload definition, multiple required
This check makes sense for a .pyi file where you would expect multiple @overloads on equal footing, but in this case the original declaration might as well serve as an "overload".
A workaround is obviously to add:
@overload
def get_item(key: str, default: Optional[Item]) -> Optional[Item]:
...
which adds needless verbosity.
I'm a little bit confused about your type signature here: if 'default' is set to None, doesn't that mean the first overload alternative will always match? So, the only case where 'get_item' can return 'None' would be if 'default' is a non-None object?
Basically, I think your type signature is equivalent to the following:
@overload
def get_item(key: str, default: None = None) -> Item: ...
@overload
def get_item(key: str, default: Item) -> Optional[Item]: ...
def get_item(key: str, default: Optional[Item] = None) -> Optional[Item]:
# implementation goes here
In any case, I think you usually want your overload signatures to be "specializations" of the implementation signature. We don't really want to force users to have the implementation signature be a valid overload alternative in that case.
I suspect that the OP intended something like this:
@overload
def get_item(key: str) -> Optional[Item]: ...
@overload
def get_item(key: str, default: None) -> Optional[Item]: ...
@overload
def get_item(key: str, default: Item) -> Item: ...
def get_item(key: str, default: Optional[item]) -> Optional[Item]:
# implementation goes here
In any case we don't have plans to make it easier to shoot yourself in the foot here.
If someone comes over this issue: The intended way of writing two different signatures, is to have them in two @overload signatures. And the actual function header for the implementation should be empty or should include the merge of all signatures with Union:
@overload
def get_item(key: str) -> Item:
...
@overload
def get_item(key: str, default: Optional[Item] = None) -> Optional[Item]:
...
def get_item(key, default = None):
# implementation goes here
...
That's why there must be at least two @overload signatures and the error error: Single overload definition, multiple required will else arise.
See also #72 , #1136 , and #3360 .
Most helpful comment
If someone comes over this issue: The intended way of writing two different signatures, is to have them in two
@overloadsignatures. And the actual function header for the implementation should be empty or should include the merge of all signatures withUnion:That's why there must be at least two
@overloadsignatures and the errorerror: Single overload definition, multiple requiredwill else arise.See also #72 , #1136 , and #3360 .