I'm overloading a method so the return type differs depending on the value of a given bool parameter. That same parameter has a default value (False in my case).
Here's a simplistic example function to demonstrate:
import typing
@typing.overload
def fn(val: int, to_none: typing.Literal[True] = ...) -> None: ...
@typing.overload
def fn(val: int, to_none: typing.Literal[False] = ...) -> float: ...
@typing.overload
def fn(val: int) -> float: ...
def fn(val: int, to_none: bool = False) -> float | None:
return None if to_none else float(val)
x = fn(5, to_none=True)
y = fn(6, to_none=False)
z = fn(7)
My problem is with z. VS Code doesn't appear to take the default value of the parameter into account and considers it a None as if True had been passed into the to_none parameter:
Is this a problem with my overload definition, or a bug with VS Code/pylance/etc.?
The overload definition of the True case is wrong: the ellipsis (...) after to_none should not be given here. That is, replace the stub with:
@typing.overload
def fn(val: int, to_none: typing.Literal[True]) -> None: ...
… and z should be inferred as float correctly.
Why is this? I quote my earlier answer to a related question, regarding the use of ellipses as placeholders for default values in stubs:
In the way the ellipses are used, they indicate that a default value is actually part of this particular overload.
In your True case, the default value (False) is not part of this particular overload (to_none: typing.Literal[True]), so no ellipsis should be written there.