Skip to content

Callable with Optional arg fails to type-check: "too many mandatory positional arguments" #442

@ryan-williams

Description

@ryan-williams

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

Typeguard version

4.1.5

Python version

3.11.8

What happened?

Passing a Callable with Optional args to another function, then calling it, results in a TypeCheckError:

TypeCheckError: argument "fn" (function) has too many mandatory positional arguments in its declaration; expected 0 but 1 mandatory positional argument(s) declared

See test_callables.py:

from typing import Callable, Optional


# ✅ type-checks fine
def _fn0(fn: Callable[[int], bool], s: int) -> bool:
    return fn(s)


def fn0(s: int) -> bool:
    return True


# ❌ TypeCheckError: argument "fn" (function) has too many mandatory positional arguments in its declaration; expected 0 but 1 mandatory positional argument(s) declared
def _fn1(fn: Callable[[Optional[int]], bool], s: Optional[int]) -> bool:
    return fn(s)


def fn1(s: Optional[int]) -> bool:
    return True


def test_fn0():
    """Passing a Callable (``fn0``) works, as long as its arguments are not ``Optional``."""
    _fn0(fn0, 123)  # ✅ OK


def test_fn1():
    """Functions that take optional arguments are not type-checked properly"""
    _fn1(fn1, 123)  # ❌ TypeCheckError: argument "fn" (function) has too many mandatory positional arguments in its declaration; expected 0 but 1 mandatory positional argument(s) declared

How can we reproduce the bug?

ryan-williams/typeguard-issues has a working repro; here's the error in Github Actions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions