Deprecated in favour of `T | None` exactly because of that embrace. It's cleaner, more consistent (you can `T | U` arbitrarily), and helps slim down the `from typing` imports.
Optional[T] is now T | None. Means exactly the same thing but doesn't require an import. Support for the older syntax presumably won't be removed for a long while regardless.
You can disable it in the pyright settings. In my opinion T | None is not a meaningful improvement and insisting on changing it everywhere causes a whole bunch of churn and needlessly makes code stop working on older Python versions.
> for some reason we need 2-3 static analysis tools just for typechecking
I don’t follow: you need one type checker, of which you have several options. It’s arguably not ideal to have more than one option, but you should never need to run more than one.
- no tool understands each other's comment directives
In general, all type checkers in Python support the `type: ignore` directive, since it’s standardized.
> each tool reports a different error in your codebase
This is a real problem, but I think you can avoid it (like most people do) by not mixing different tools that do the same thing together.
To my understanding, you’d have the same problem if you combined (e.g.) biome and eslint in a JavaScript codebase.
I have to use more than one Python type checker because there is not a single one that works. Not only different tools catch different issues. They also have different bugs, and different configuration requirements. Different teams have different preferences.
It's a nightmare. If Python taught me something about typing is that a language that doesn't have a clear definition of types in the reference implementation, it will never get it fixed with external tooling.
It's a complete ergonomic travesty that Python doesn't have one.
I personally prefer the fake typing in Python because it fits well with our defensive programming style with very low abstraction and little to no adherence to DRY. Since Python naturally force you to deal with runetime assertions rather than getting you to do compiletime checks that then don't actually offer any form of safety at runtime. Which is obviously not a very technical argument, but it just feels a lot cleaner rather than having to juggle the two.
I don't get how uv regularly gets recommended without any note about this.
Can you say more? uv should always tell you if a wheel build fails, unless the build backend (which uv doesn’t control, unless you use uv’s own backend) decides to silently ignore a wheel build. This would be a bug in any given build backend IMO.
This is an unfortunate complexity in Python packaging: something like `uv build` can dispatch a wheel build for you, but the actual code that gets run as part of that build is often third-party build backend code that uv itself has little to no control over.
I think Python is probably good for many things, including scripts and as a starter language, but I don't understand how anyone can stand writing large software systems in it.
The main difference is that in the JS ecosystem it is all installed at the project level, you don't need anything globablly installed besides the runtime and package manager (and even the package manager can be auto-installed as well if you set it up that way).
[1]: eslint, biome, prettier, scass linter, graphql-codegen, tsc, tanstack-router codegen. That I remember, might be more (although codegen might not be considered static analysis, it is needed for static analysis).
So same as JS then.
I have switched type checker recently in my own Python projects from zuban to ty. ty seems to work better, and is not a one man show/bus factor of 1, though I respect the work that has gone into zuban by its creator. But ty doesn't understand mypy configuration in pyproject.toml ...
I imagine switching a type checker in a bigger project and with more people involved to be a bit of a PITA, until everyone has adjusted their development environment/tooling. Best one can do is research beforehand which tool suits one best, test it, and then stick to it, unless it has unbearable failures.
Rather I prefer not to be in the same spot I was in 1999 - 2001, with Tcl, and every now and then rewriting code into C, for the application to actually deliver within the performance deadlines.
Python is the only mainstream dynamic language where runtime support for dynamic compilation is such an hassle, where the alternatives do exist, yet are mostly ignored.