Closures and type hints (in VS Code)

When I try to type hint my closure, I get worse suggestions than without:

from typing import Callable, Protocol


class _FormatterProtocol(Protocol):
    def __call__(self, *values: object, sep: str = " ") -> str:
        """Apply ansi formatting to values."""


def _make_formatter(start: int, end: int):
    def formatter(*values: object, sep: str = " ") -> str:
        """Apply ansi formatting to values."""
        return f"\x1b[{start}m{sep.join(map(str, values))}\x1b[{end}m"
    return formatter


yellow1 = _make_formatter(33, 39)
yellow2: Callable[..., str] = _make_formatter(33, 39)
yellow3: _FormatterProtocol = _make_formatter(33, 39)



Possible solutions:

def _formatter(*values: object, sep: str = " ") -> str:
    """Apply ansi formatting to values."""
    raise NotImplementedError


class _FormatterCallable(Callable):
    @abstractmethod
    def __call__(self, *values: object, sep: str = " ") -> str:
        """Apply ansi formatting to values."""


class _FormatterCallableProtocol(CallableProtocol):
    def __call__(self, *values: object, sep: str = " ") -> str:
        """Apply ansi formatting to values."""


yellow4: ((*values: object, sep: str = " ") -> str) = _make_formatter(33, 39)
yellow5: _formatter = _make_formatter(33, 39)
yellow6: _FormatterCallable = _make_formatter(33, 39)
yellow7: _FormatterCallableProtocol = _make_formatter(33, 39)

Or just: special case protocols with only a __call__() method.

When you say “suggestions”, you mean tooltips in an editor, right?

Which editor is this? That should probably feature in your post title

VS Code, I kind of expected more people to be familiar with it.

Which plugin are you using? This sounds like a feature request to them. (At a guess, I’d say it’s probably going to end up on pylance?)

I’m using the Pylance extension.

  • yellow2 is 100% expected behavior. You are explicitly telling the type checker that this variable can refer to any callable that takes any number of arguments of any type and returns a str. If that isn’t what you, don’t write that down.

  • yellow3. I guess the highlighter could special case such protocols. But that isn’t something that is really all that useful to raise as an issue here, go tell the devs of the tool you are using.

yellow2 is mostly fine in this specific use case, but unfortunately it can’t include the sep argument.
For callables as arguments, keyword arguments aren’t all that useful, but for closures they are.

I guess it works as intended in Pylance. (Type aliases aren’t expanded too).
It’s just sad I can’t type hint everything. (Without losing helpful information).