Python now has five type-checkers, and a blog says run all of them
One seven-line function in the Polars library needs four different type-ignore comments to satisfy four different checkers. The advice that followed: run as many as you can on your tests.
mypy, Pyright, Pyrefly, ty and Zuban now all check Python types, and each disagrees about what is valid. A post from the Pyrefly team shows a single Polars __eq__ override carrying four separate ignore comments for seven lines of code, then argues the fix is to run every checker you can against your test suite rather than your source.
The thread split hard. One camp asks why dynamically typed Python is being bolted into a strict-typing house of cards; another insists that for code where bugs have real consequences, the checkers earn their keep.
Five checkers, four ignore comments, seven lines of code

The headline of the Pyrefly team's post is a genuine question library authors now face: with mypy, Pyright, Pyrefly, ty and Zuban all checking Python types — and each implementing the partially-standardized typing spec slightly differently — are you really expected to run all of them? The post's exhibit is a single __eq__ override from the Polars dataframe library. To pass every checker, the seven lines need four different suppression comments stacked on top of each other:
@overload # type: ignore[override]
def __eq__( # pyrefly: ignore[bad-override]
self, other: pl.DataTypeExpr
) -> pl.Expr: ...
@overload
def __eq__(self, other: PolarsDataType) -> bool: ...
def __eq__(...): # ty: ignore[invalid-method-override] # pyright: ignore[reportIncompatibleMethodOverride]
The post's own reaction: "Wow, that's 4 different type-ignore comments for just 7 lines of code!" The reason == doesn't return a bool here is the same reason it doesn't in numpy or SQLAlchemy — overloaded operators build query expressions or element-wise boolean arrays, not a single truth value.
The actual recommendation: check your tests, not your source
The post's thesis inverts normal practice. Instead of pouring effort into type-checking your own source, it argues: "Prioritise running as many type-checkers as possible on your test suite. Run at least one on your source code." The logic is that a library's users each run a different checker, and what they care about is whether your public API produces errors in their setup. The same Polars function that needed four ignore comments in the source passes all five checkers cleanly when exercised through a test — so the test is where multi-checker coverage actually buys you something.
The story's submitter, active in the thread, framed why this is a Python-specific tax:
"Running more type checkers isn't really about strictness… Python's typing ecosystem is uniquely fragmented, with only partial standardization between several popular tools." — the post's submitter
The thread: "the laziest of all is mypy" and other field notes
The discussion turned into a working comparison of who runs what and why. The practitioner splits:
| Voice | Setup / take |
|---|---|
| Runs both in parallel | pyright in CI, mypy locally — they catch different bugs |
| mypy skeptic | mypy is "dog slow" and "the laziest of all," misses many mistakes |
| uv loyalist | ty + ruff are enough; sees no reason to add a checker |
| PyCharm holdout | its built-in inference beats the standalone tools through deep inheritance |
The parallel-runner was blunt about why you can't just pick one:
"I run pyright in CI and mypy locally. They catch different things - pyright is stricter on overloads, mypy catches more None issues in our codebase. Annoying, but I have not found one that covers both." — an engineer running two checkers in CI
"Why anyone would still use mypy besides legacy infrastructure is beyond me. It is dog slow as well as being the laziest of all, not catching many mistakes." — a Django developer frustrated with mypy
One high-karma commenter offered a TOC-worthy summary of the new tooling consensus: "Everything that isn't uv, ty, ruff is wrong and deprecated" — to which a reply asked whether he'd update that list a month from now.
The deeper split: should strict typing be in Python at all
Under the tooling complaints sat the real argument: gradual typing in a dynamic language as a category error. A skeptic asked why, if you're going to be this strict, you wouldn't just move to a statically typed language and get the performance too. The counter came from people who don't have that choice:
"There are lots of people who like python and want to use it for things [where] incorrect code has serious consequences. Type checking is helpful in these contexts… pushing away people who want to use all available tools for writing correct python only hurts the community." — a developer defending optional strictness
"type checked Python is better than nothing." — a commenter on those without a choice of language
The sharpest dissent argued the whole premise is overblown — that exceptions from a wrong type aren't catastrophic, and finding errors by type-checking is functionally no different from finding them with the test suite every production codebase already has. One commenter laid out why even "strict" typing rarely delivers what its fans imagine:
"every type defined [would need] a finite range of values… If you have this system, (something like Coq comes close), then if your program compiles, its by definition correct. But even the strongest proponents of typing don't really want to do this, because they realize how long it would take to write code." — a Python-in-production skeptic
And a wish-list comment described the typing system many wanted instead: inferred-by-default, constraint-based, where you'd write def foo(a, b): return a + b and the checker would tell you foo(5, {}) fails because there's no + for int and dict — annotations only when you want to tighten the inferred constraints, not restate the obvious.
The so-what: the fragmentation is the product
The post's advice isn't really "run five checkers" — it's a coping strategy for library maintainers whose users have scattered across five tools that don't agree. For application developers the takeaway is narrower and more useful: pick one checker for your source, and if you ship a public API, exercise it through tests under whatever your users actually run. The recurring thread complaint — that this is all a lint step bolted onto a duck-typed runtime, so you pay for both — is the part no amount of tooling fixes.
Get breakdowns like this every day
The top Hacker News stories, unpacked — by email, Telegram, or RSS.
A Rust 'better GitHub' launched as anti-AI, then dang cut that from the title
Gitdot pitched itself as a faster, open-source GitHub that won't ship AI. Commenters opened its own source, found a dozen CLAUDE.md files, and within hours a moderator had quietly removed 'anti-AI' from the Show HN title.