Skip to content

default value for overloaded optional parameters #7333

@crusaderky

Description

@crusaderky

Python 3.7.4, typing_extensions 3.7.4, mypy 0.720

I'm trying to use Literal and @overloadto change the result type of a function depending on a boolean switch.
This issue is not specific to Literal, but it makes it easier to produce an easy to understand real-life use case.

Everything works great as long as the parameter is mandatory:

from typing import overload, Optional
from typing_extensions import Literal


@overload
def plusone(x: Optional[int], none_to_zero: Literal[True]) -> int:
    ...


@overload
def plusone(x: Optional[int], none_to_zero: Literal[False]) -> Optional[int]:
    ...


def plusone(x, none_to_zero):
    if x is None:
        if none_to_zero:
            x = 0
        else:
            return None
    return x + 1


plusone(None, True).to_bytes(4, "little") # ok
plusone(None, False).to_bytes(4, "little") # not ok

mypy output: 25: error: Item "None" of "Optional[int]" has no attribute "to_bytes"

However, if I set a default value:

from typing import overload, Optional
from typing_extensions import Literal


@overload
def plusone(x: Optional[int], none_to_zero: Literal[True] = True) -> int:
    ...


@overload
def plusone(x: Optional[int], none_to_zero: Literal[False] = True) -> Optional[int]:
    ...


def plusone(x, none_to_zero=True):
    if x is None:
        if none_to_zero:
            x = 0
        else:
            return None
    return x + 1


plusone(None, True).to_bytes(4, "little") # ok
plusone(None, False).to_bytes(4, "little") # not ok
plusone(None).to_bytes(4, "little") # ok

mypy output:

11: error: Incompatible default for argument "none_to_zero" (default has type "Literal[True]", argument has type "Literal[False]")
25: error: Item "None" of "Optional[int]" has no attribute "to_bytes"

Workaround
Add # type: ignore on line 11. The error on line 25 is still reported.

Expected behaviour
In each of the signatures of an @overload'ed function, the allowed default values of an optional parameter should be the Union of type annotations from all the signatures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions