NamedTuple to support Callable lambdas
Description
pyright doesn't support inferring the type of lambda from a NamedTuple:
from typing import NamedTuple, Callable
class Foo(NamedTuple):
a: int
b: Callable[[str], str]
bar: Foo = Foo(10, lambda x: x.lower()) # Type of parameter "x" is unknown
You can see this in the plyaground with a normal tuple working just fine
foo: tuple[int, Callable[[str], str]] = (10, lambda x: x.lower())
Upstream has decided that
[...] pyright is working as intended here, so I don't consider this a bug.
Original closed issue https://github.com/microsoft/pyright/issues/9110
Seeing as they don't intend to fix this upstream, I figured I may as well open an issue here.
mypy handles this case just fine
from collections.abc import Callable
from typing import NamedTuple
class Foo(NamedTuple):
a: int
b: Callable[[str], str]
bar: Foo = Foo(10, lambda x: x + 5)
> uvx mypy .
main.py:10: error: Unsupported operand types for + ("str" and "int") [operator]
Found 1 error in 1 file (checked 1 source file)
yeah i don't see why this shouldn't work. i don't understand the argument in https://github.com/microsoft/pyright/issues/9110#issuecomment-2383770629 about the __init__ and __new__ methods. since the signatures are supposed to always match i don't see why pyright would need to check both when validating the call.
it also seems like the stub has changed since that comment was made. NamedTuple's __init__ now looks like this:
class NamedTuple(tuple[Any, ...]):
@overload
def __init__(self, typename: str, fields: Iterable[tuple[str, Any]], /) -> None:
...
@overload
@typing_extensions.deprecated(
"Creating a typing.NamedTuple using keyword arguments is deprecated and support will be removed in Python 3.15"
)
def __init__(self, typename: str, fields: None = None, /, **kwargs: Any) -> None:
...