Click CLI type-checks under mypy strict without `# type: ignore[misc]`
#456 opened on Jun 26, 2026
Repository metrics
- Stars
- (24 stars)
- PR merge metrics
- (PR metrics pending)
Description
Summary
Remove the blanket # type: ignore[misc] comments scattered across the Click CLI surface, replacing each with a properly typed construct so mypy --strict passes without suppression.
Motivation
There are 19 # type: ignore[misc] sites: 17 on the @click.command() / @click.option(...) / @click.argument(...) decorators in cli/main.py, one on EnumChoice(click.Choice) in cli/click.py, and one on ZFSReplicateError(ClickException) in error.py. They predate Click shipping inline type information (py.typed); the lockfile now resolves Click 8.1.8 (8.4+ in a fresh env), which is fully typed.
A quick check stripping the ignores from those three files and re-running mypy left only one real error — error.py:8: Class cannot subclass "ClickException" (has type "Any") [misc] — which suggests most of the decorator/Choice ignores are already stale and removable, while the ClickException subclass still needs a typed path. They mask whatever future signature mistakes mypy would otherwise catch on these decorators.
Surfaced while adding the receive-side flags in #393 / #455, where each new @click.option had to carry another copy of the ignore.
Scope
- Audit the 19
# type: ignore[misc]sites incli/main.py,cli/click.py, anderror.py. - Drop the ones mypy no longer needs now that Click is typed.
- For any genuine remaining gap (e.g. subclassing
ClickException), find a typed resolution — a typed shim, a narrower per-line ignore code, or a documented minimal suppression — rather than the broad[misc].
Acceptance criteria
-
mypy --strict(the repo'smypy.ini) passes onzfs/with no# type: ignore[misc]incli/main.py,cli/click.py, orerror.py. - Any unavoidable suppression that remains uses a specific error code and a one-line comment explaining why, not a bare
[misc]. - No new
# type: ignoreis introduced elsewhere to compensate.
Additional context
Overlaps #398 (drop Python 3.8/3.9 for v5.0.0), whose acceptance criteria include re-evaluating these same # type: ignore[misc] markers. This issue does that re-eval standalone, independent of the version-matrix change, so it can land first — closing it satisfies that slice of #398 early. Implemented by #458.