8 ms·
Are you expected to run five Python type-checkers now?
- woeirua 4mo agoWith agents it no longer makes sense to tie yourself to Python's archaic development experience. How many type checkers are there? Package managers? Don't even get me started on cross-platform deployment. Strongly typed, compiled languages have never been easier to use, and agents reap huge benefits from the tight feedback loop that the compiler provides. Moreover the benefits of the Python ecosystem are less significant today than anytime in the past 20 years. Need something that's only available in Python? Just point some agents at it and you can port it.
- voidUpdate 4mo agoWhat about the several people worldwide who don't want to use LLMs to program?
- cryptonym 4mo agoThey also "reap huge benefits from the tight feedback loop that the compiler provides". When something is easier/requires less context, it tends to work well for both human and LLM.
- vips7L 4mo agoI've noticed this a lot in LLM generated Java. Since it doesn't know what can or can't be null it tends to wrap everything in Optional<T>. Super strong type systems are becoming even more important.
- hedora 4mo agoYou probably need to tell it to rip as many of those out as possible (and replace them with null annotations). I've noticed LLMs sometimes pick a documented anti-pattern (passing Optional around in Java is not recommended), then amplify it (like a human might).
- vips7L 4mo agoThat's because LLMs suck.
- datsci_est_2015 4mo ago> Just point some agents at it and you can port it. Don’t think we’re there yet, otherwise we would see a bunch of forks of major libraries to alternative languages - and not just Python. There’s still too much risk of insidious errors and bugs.
- hedora 4mo agoI've done thus a few times for stuff in the < 10,000 LOC space. It works great. There's something particularly satisfying about shipping a 1-10MB static rust binary instead of a 2GiB docker python environment. (I'm talking about just porting simple applications, or maybe a missing package/crate at a time. Not both at once, and not typical 100K-10M line internal legacy sprawl)
- datsci_est_2015 4mo agoWhat have you ported, for example? Any 3PL or all internal code?
- voidUpdate 4mo ago> "In Python, any method __eq__ is expected to return bool, and if it doesn't, then we need to explicitly tell type-checkers to ignore the type error. This function in Polars can also return different types depending on the inputs, thus requiring overloads." Why would you ever want a == b to not return a bool?? EDIT: Yes, I understand that you can do element-wise equality checks on numpy arrays now
- datsci_est_2015 4mo agoOne example is if an and b are arrays (e.g. numpy arrays) it’s not unreasonable for dunder eq to return an array of booleans. Another example might be if you have a domain specific representation of equality (e.g. class Equality)
- voidUpdate 4mo agoI can see the first one making sense, but why would you need a representation of equality other than "yes, these are equal" and "no, these are not equal"?
- datsci_est_2015 4mo agoWell personally I’m not a fan of turning everything into an object, but if you have properties or methods that exist upon the concept of Equality you might want to encode directly onto a class. Maybe in a domain where “Equality” is an important concept, like mathematics or even something like accounting. Could enable a different interface into approximate equality for floating point numbers: Equality.approximate(iota: float) -> bool
- agons 4mo agoThe first use case that comes to mind is if you want a DSL to build expressions that are evaluated later in some different context e.g. when using `polars`: ```python df.filter( pl.col("foo") == pl.col("bar"), ) ``` Sqlalchemy does something equivalent too, and I'm sure there are many others.
- 4mo ago
- dsign 4mo agoIf you are going to be super-strict with type-checking, wouldn’t it be best to switch to a statically typed language and get the performance gains as well?
- ocamoss 4mo agoRunning more type checkers isn't really about strictness. The main benefit to library maintainers is to make sure that their APIs are compatible with whatever tools their users run. This wouldn't really be an issue for most other languages, but Python's typing ecosystem is uniquely fragmented, with only partial standardization between several popular tools.
- deleted 4mo ago[deleted]
- fg137 4mo agoHmm... that doesn't answer the question?
- locknitpicker 4mo ago> Hmm... that doesn't answer the question? GP's point is obvious: performance is immaterial to the discussion. Static code analysis is about preventing bugs. Therefore OP fails to make any sort of point, as it's a straw man argument.
- deleted 4mo ago[deleted]
- pmontra 4mo agoHallelujah, that's always been my position. To the static typing folks: leave my dynamically typed languages alone and go coding with something that really suit your needs. If the answer is that Python, Ruby, JS, whatever are really much more pleasant to code with, my reply is that they are so precisely because we don't have to type type definitions. Tradeoffs.
- blahgeek 4mo ago> Prioritise running as many type-checkers as possible on your test suite. Run at least one on your source code. There are two types of tests: those that test against the public API, and those that test internal codes with various mocks and fakes. I think the vast majority of unit tests is the latter one, in which case the suggestion does not really make sense.
- kingstnap 4mo agoThe fact that this article seems to honestly recommend people run 5 different type checkers on library test suits really reflects the tacked on feeling of Python typing.
- vitorsr 4mo agoI am not sure it is recommending more than it is commenting on the current state of developing public-facing APIs in Python. The downstream users that import the package either have to ignore checking its exported types altogether, manually stub it, or have a subpar development experience to varying degrees. This is something I saw the other day with some package that provided comprehensive stubs for an untyped library. The .pyi file was littered with comments about quirks from the numerous type checkers (five now).
- TremendousJudge 4mo agoIt's ridiculous. They should have made it an explicit part of the language. The interpreter knows about types already, it's crazy that they couldn't just let the user make the types explicit rather than implicit, and have the interpreter enforce that.
- mort96 4mo agoThe interpreter knows types at runtime, not at parse/compile time. The interpreter already does a lot of dynamic type checking. It has a much stricter type system than e.g JavaScript; JavaScript will pretty much always convert operands to produce some result (even if it's just NaN or the string "object Object"), while Python will often just give you a type error. The interpreter doesn't know about static types. I agree that they should've made typing more a proper part of the language and not left it in this weird half-defined state of "standard syntax and some standard typing imports but undefined semantics". But it's not just a matter of enforcing existing types.
- ActorNightly 4mo agoNo, it reflects the nature of misunderstanding Python by people who think their system is better, have no idea how Python in production actually works, and just publish things like the article to make themselves feel better. Typing is not a huge issue, period. In Python, if you pass a wrong type to something, program just throws exceptions. Exceptions are not the end of the world like people make it seem. Functionally, finding errors during the process of taking code and compiling it with type checking is no different than taking code and just running it against a set of tests, which every production code has (or should have) The only waytyping ever saves you from it is by being absolutely strict - every type defined has a finite range of values, and every operation has bounded domain and range. I.e if you have a string field, its not enough that its a string, you also must define the total number of characters that string can have, and values for each character, along with more complex rules on sequences of characters. 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. The simple truth is that Python is easy and flexible enough to work in that you don't even need type checking. An LLM can effectively function as a type checker for you if you care enough. For any errors that you encounter due to lack of typing, its ultimately way faster to fix with Python than it is to spend time writing strongly typed language.
- shermantanktop 4mo agoThat blog needs to run a AI checker. Content aside, a lot of the writing is pure AI style. > The type checking that matters most (and why you've probably got it backwards) Honestly, I don’t care if the author got some AI help. But that click-bait style is ubiquitous and obnoxious.
- faangguyindia 4mo ago[dead]
- ghostly_s 4mo agoWhy would users care if you're using the same type checker as them? Surely they're not expecting all their imports to be instrumented for running redundant types checks?
- Someone 4mo agoUsers do not care about that, but they want to not see type errors or warnings when they integrate your API in their code. That’s why you want to run their type checker on your API. you cannot know what “their type checker” is, so you want to run all popular type checkers on your API.
- ForHackernews 4mo agoSounds like a them-problem. Their type checker can accept my declared typings for my public API, or they can override it with their own custom type stubs if they have objections.
- KolmogorovComp 4mo agoWhy 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. Unfortunately for Django apps switching to any alternative leads to the dreaded “wall of errors” issue. If anyone got to work this out in the past, I’d gladly take advices.
- thr1owaway9621 4mo agoI use pyright with a 50k LOC Django REST API codebase. I haven't really had problems. From my pyproject.toml: django==4.2.30 djangorestframework==3.16.1 --- django-types==0.15.0 djangorestframework-types==0.8.0 pyright==1.1.390 My dj version is pretty old, but I'd assume things have only gotten better since v 4?
- cptmurphy 4mo agoThe django mypy plugin can inspect django models types, project settings and much more context.
- Syntaf 4mo agoWe switched our very large Django monolith codebase over to ty — the trick for us was generating stubs for Django models and having tooling keep those stubs in sync with the actual models. Went from type checking taking ~10 minutes in CI to now taking ~15 seconds and runs on pre-commit. Absolute game changer, I think we spent $10k in claude credits and did the entire mypy -> ty refactor in about 3 weeks.
- shevy-java 4mo agoThe type-lovers will be angry! :) The blog entry fits into ruby too, to some extent; while the situation is nowhear near as bad as in python, you have the same question-marks why types suddenly emerge out of nowhere. Almost ... almost as if some people have a specific agenda, and try to pull through with it. Well, there you have it - the type-addicted people are ruining python.
- prodigycorp 4mo agowhat are ppls' impression of pyrefly? i've become completely captive to uv's tooling. it has allowed me to think only about coding versus tooling. dont feel like giving another typechecker a chance unless it offer's something i'm not getting from ty.
- zerof1l 4mo agoFrom my experience with Python, both personal and professional, I find it immature and not well-suited for large codebases. Typing should have become part of the language a long time ago; it is clear that users want it. Take, for example, PHP… look at the features released in the last 6 or so years, starting with PHP 7, and how mature the language has become. With the advance of AI-assisted programming, I feel like Python is always a bad choice.
- __mharrison__ 4mo agoI'm happy w/ ty right now. My agents runs it fast and it seems to provide great guardrails.
- semiinfinitely 4mo agoEverything that isn't uv, ty, ruff is wrong and deprecated
- pvdebbe 4mo agoWill you update the list for us, a month from now?
- throawayonthe 4mo agoi doubt uv and ruff are going anywhere that quickly at least
- VoidWarranty 4mo agoDynamically typed languages are going to decline with the rise of AI coding. Statically typed languages provide the determinism necessary to efficiently anchor probabalistic coding agents. You can throw as much type checking at dynamic languages after the fact, but youre just going to burn energy (and tokens) doing what another language gets 'for free'.
- necovek 4mo agoI am not so sure that's this simple. No matter your preference, programs in dynamically typed languages are still very much deterministic. To be able to reason about the output of LLMs (though it is debatable how often will this be needed), you want the output from your imprecise human language spec to a deterministic spec (code) to be as easy to review as possible (for correctness, but mostly for any glaring errors). With proper setup, ensuring correctness of one deterministic output (Python) in comparison with another (eg. typed language like Rust) is just a deterministic run away (a test suite) that should not use any tokens from the LLM, and should have no practical differences in compute use.
- fasterik 4mo agoStatic type checking catches a whole class of programming errors for free. Writing tests costs tokens or human time, so you end up needing more code (and probably more CPU time) to achieve the same level of error-checking in a dynamic language.
- necovek 4mo agoVery simplistic look, IMO. I'll add another one mostly as a counterpoint (not that I believe it is strictly true, but largely yes!). Python is a lot more expressive than other languages and has a very terse syntax, and thus requires LLM to output much fewer tokens to achieve the same job compared to other languages. Adding a few more tests to ensure data conformity on top of what you have to do anyway with a statically typed language still results in fewer tokens overall.
- leni536 4mo agoThis is what the typing spec says about type narrowing[1]: "Type checkers should narrow the types of expressions in certain contexts. This behavior is currently largely unspecified." Have fun. [1] https://typing.python.org/en/latest/spec/narrowing.html#type-narrowing https://typing.python.org/en/latest/spec/narrowing.html#type...
- braiamp 4mo agoWhat is this saying differently from https://peps.python.org/pep-0827/ https://peps.python.org/pep-0827/ ?
- ocamoss 4mo agoEverything? The blog post and PEP have almost nothing to do with each other lol
- throwawayffffas 4mo agoThe whole type checking experience in python has disappointed me deeply and is seriously affecting my work. I see the appeal for type-checking and yeah it has caught many bugs. But the language is quickly running blindly to the worst of all worlds in regards to typing. 1. You have to exhaustively write types in many cases where they can be obviously inferred. 2. The type checking is just a lint step. i.e. we are still paying for the duck typed typing system. 3. We no longer get to use the duck typed typing system making a lot of generic code require obscure annotation incantations to pass the lint check while it's correct python code. My ideal typing system would be around constraints introduced by the code and completely inferred unless the user wants to tighten the constraints. i.e Instead of def foo(a: int, b: int) -> int: return a + b You would write: def foo(a, b): return a + b And upon checking if you tried to do foo(5, {}) It would tell you that there is no + operator for int and dictionary that is required by the foo function. My ideal typing system would allow you to constraint the types as well like so def foo(a: int, b: int): return a + b The return type is not required in this case because it can be inferred by the function definition. For other cases it could be defined as well to constraint that we don't want None for example.
- HelloNurse 4mo agoDeclaring types only where one wants to introduce a constraint would be nice, but unfortunately calls with obvious wrong types like "foo(5, {})" are a minority; in most cases types in a call depend on types of the calling function's parameters, and the type checker can only deduce unknown type from unconstrained type. Moreover, the extremely dynamic execution and lack of compilation in Python means that determining in a lint step whether "there is no + operator for int and dictionary" is essentially impossible: if you find some __add__ or __radd__, you need to trust its declaration that it accepts certain types or not and hope it's still there at runtime; if you don't find it, it might exist at runtime when operator + is actually used. A compiled and sufficiently static language, on the other hand, can inspect source code and libraries and reason about potentially infinite sets of definitions and prove that functions exist or don't exist.
- throwawayffffas 4mo ago
- stephbook 4mo agoFive different type-checkers and even type-checking projects think adding multiple "ignores" is sound code. Typescript would allow overloads without ignores, for example. Python's type checking ecosystem truly is a mess.
- insane_dreamer 4mo agoI use ty with Zed. But PyCharm's built-in type checker is far and away the best that I've used with proper type inference through multiple class inheritance hoops.
- pantafive 4mo ago[dead]
- ryanshrott 4mo agoI 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.
- emeryberger 4mo agoSince we are talking about Python type-checkers: we've built a (non-AI based) type assistant for Python called RightTyper (https://github.com/RightTyper/RightTyper https://github.com/RightTyper/RightTyper). Below is a brief description; a technical paper describing RightTyper is here: https://arxiv.org/abs/2507.16051 https://arxiv.org/abs/2507.16051, "Getting Python Types Right with RightTyper" RightTyper is a Python tool that automatically generates type annotations for your code. It monitors your program as it runs and records the types of function arguments, return values, local variables, and class fields — with only about 25% runtime overhead. This makes it easy to integrate into your existing tests and development workflow, and lets a type checker like mypy catch type mismatches in your code.