Repository navigation
Indicate in the docs that static typing doesn't work with lambda functions #2020
Description
Activity
- addedtopic: documentationDocumentation-related issues and PRsDocumentation-related issues and PRs
on Jun 7, 2025 Because lambdas syntactically do not allow annotations, type checkers have to infer parameter and return types for them, but that doesn't mean they "can't be type-checked". For example, given this program:
def f(lst: list[int]): reveal_type(list(map(lambda x: str(reveal_type(x)), lst)))
Pyright reveals
intfor the inner call andlist[str]for the outer call, correctly.However, in a lambda that is not passed as an argument or in a more complicated situation, type checkers may not be able to infer a type.
I don't think it makes sense to change the spec here; this seems more of a topic to discuss in user-facing documentation.
Building on what Jelle said, static typing does work with lambdas, and all lambdas are type checked. As with some other expression forms, there are cases where a type checker doesn't have sufficient information to infer types, so it will fall back on
Any(orUnknown) to fill in the missing type information. Lambdas are not unique here.For example, this program type checks with no errors (using default settings in pyright) thanks to gradual typing.
def x1(a, b): return a + b x2 = lambda a, b: a + b x3 = [] reveal_type(x1) # (a: Unknown, b: Unknown) -> Unknown reveal_type(x2) # (a: Unknown, b: Unknown) -> Unknown reveal_type(x3) # list[Unknown]
If you want to catch more potential errors statically, you can supply additional type information. In the case of a
defstatement, this can be done by adding explicit parameter type annotations. For a lambda, an empty list, and various other expressions whose types cannot be inferred without additional context, an explicit type declaration for the target variable can be added.def x1(a: int, b: int) -> int: return a + b x2: Callable[[int, int], int] = lambda a, b: a + b x3: list[int] = [] reveal_type(x1) # (a: int, b: int) -> int reveal_type(x2) # (a: int, b: int) -> int reveal_type(x3) # list[int]
The typing spec doesn't dictate type inference behaviors for type checkers, but most type checkers support some form of bidirectional type inference to handle situations like this.
I agree this would make a good addition to the user-facing documentation. The Type System Guides would be a good place for this. Documentation contributions are always welcome!
Reacted by wyattscarpenterHowever, in a lambda that is not passed as an argument or in a more complicated situation, type checkers may not be able to infer a type.
I don't think it makes sense to change the spec here; this seems more of a topic to discuss in user-facing documentation.
Yes, that is what I was suggesting - to explain it better and the suggestion made here:
agree this would make a good addition to the user-facing documentation. The Type System Guides would be a good place for this.
is a good one. It's examples like this that trip people up:
f1 = lambda a, b: a * b f1([1, 2], [3, 4])
Unfortunately, a static type checker won't flag the call to
f1as incorrect, and I think this is where some of the confusion lies in that thelambdafuncs are callables that by default have untyped arguments and untyped results, and for this kind of case, I'm not sure what you'd have to do to get the types right so that the*operator works when you expect it to, e.g.,f1([1,2], 3)is valid, as isf1(3,4)andf1(3, [1,2]).The recommendation that I give to people is if you want type checking in the
lambdafunction, then you either need to convert it to a regular python function with typed arguments and return types, or declare it as aCallableas suggested above.
I sometimes get asked why a
lambdafunction can't be type-checked. And I believe the answer is that the arguments and result of alambdacan't be inferred by a static type checker.It might be worth adding something at https://typing.python.org/en/latest/spec/callables.html#callables that tells people that
lambdafunctions can't be type checked (or if they can, what are the restrictions), and that the workaround is to create a typed functiondefthat does what the lambda does.