HACKER Q&A
📣 triyambakam

Which Python type checker should I use?


New to Python but not new to type checking (Rust, Typescript). I don't know which type checker for Python I should invest in.


  👤 drekipus Accepted Answer ✓
Pyright is the Microsoft provided lsp: does anyone else feel uneasy about using this? Especially given the EEE playbook "that we definitely won't do this time" - would love to have a discussion on this if someone could talk me into using it.

I just use a combination of black, flake, and mypy. Apparently ruff is quite good as well. For lsp I use Jedi, which actually worked faster on my company's code base than pyright, a year or so ago.


👤 damezumari
I would not personally use any of them. Typed python in previous workplace was pretty much shitshow, and if starting from scratch instead of untyped codebase it might be worth it, maybe, for some specific cases, but in general combination of bad library typing and bad type checking tools leads to horrible user experience.

So going forward my personal projects continue to be ducktyped, and if I care about types, I use rust or go.


👤 Zizizizz
Pyright by default because it's a LSP so I get to go definition, find references, etc... as well as the type checking in neovim. It's Pylance as part of the Python plugin in VS Code. Just make sure you go to the settings in Vs code and turn the type checking on to basic or strict. (It's off by default)

I tend to run mypy every now and then ad-hoc to check things and it sometimes finds things that need correcting but I wouldn't say it's as worth setting up as the former.


👤 _ZeD_
(eclipse+pydev - for the IDE part) + mypy (better dmypy for performance) + ruff (both as linter and as formatter) is the way I go.

an in my pyproject I set the strict mode for mypy, and almost all rules for rust with extend-select


👤 thoaasfwe
pyright is state of the art right now thanks to eric. If you use VSCode+Pylance you will feel right at home coming from Rust/TS.

just be aware a lot of community packages aren't ready for typed python. if you stick to the good stuff like fastapi and pydantic, you will be fine.


👤 smitty1e
The recent takeover of rye by the guys doing ruff[1] has some likelihood of rendering the python typing and packaging scene into something more coherent.

Having the tool get started with Ronacher, of Flask fame, gives it some mindshare among those paying attention.

It would be better still if the PSF were endorsing, but that gets too political, I suppose.

[1] https://astral.sh/blog/uv


👤 fbdab103
Would also be interested in what is friendly with Django. Using VSCode + the Python extension, the default checker (Pylance?) just pukes on the ORM magic.

👤 IshKebab
Pyright is much much much better than Mypy, and it's easy to use with VSCode. The only reason to use Mypy is if you're adding types to a legacy codebase and don't want to be immediately confronted with a gazillion type errors, because Mypy has "eh whatever" modes and is generally more lax.

If it's new code, Pyright hands down.


👤 MrJohz
My experience is pretty negative with all of them, I would be almost more tempted to ignore type checking in Python until it has drastically improved. In particular, if you're experienced with Typescript, you're probably going to be very disappointed when trying to do similar things in Python.

The most recent one I've tried was Pyright. Pyright is faster than Mypy, and can also be configured to be quite strict, both big plus points for me. Unfortunately, in practice it ended up being far too strict in weird ways, and therefore difficult to work around with libraries that don't share its idiosyncratic assumptions.

For example, in Typescript there's an unknown type, which you can't do anything with unless you check its runtime type first. It's a clever way to add a true dynamic type to the type system without losing type safety. In Pyright there's a similar Unknown type, but in strict mode the type checker simply throws an error if anything is ever unknown. For me, this turned out to be particularly painful when using library types that involved generic state. Because I wasn't using that state, I didn't set a type for it, and it defaulted to Unknown. But that meant that an object had Unknown properties (that I was never using) which meant the type checker kept on failing. Moreover, because Python's generics story is pretty miserable, I couldn't figure out how to set the type to something not Unknown. And I couldn't figure out how to disable the error because Pyright's documentation is so poor. I genuinely spent a day of work on this problem, then disabled type checking completely because that was the easiest option.

I haven't used Mypy for over a year at this point, so things may well have changed, but my memory was that where Pyright is overly pedantic, Mypy was overly lax. It was also a lot slower, and had similarly poor documentation. The main reason I switched was that I was still regularly running into runtime type errors - the very errors that the type system was meant to help me avoid.

In both cases, I found the biggest problem was that neither tool seemed to go as far as Typescript in terms of modelling real-world Python code. What I mean by that is that idiomatic Typescript usually looks a lot like idiomatic Javascript in terms of the patterns and features used, because the Typescript team have put a lot of effort in to ensure that Typescript types represent how Javascript is actually used.

On the other hand idiomatic typed Python typically seems to look very different from idiomatic untyped Python, in large part because with types, you end up limited to about 1/4 of the surface area of the language. (This is why a lot of major libraries or tools come with type checker plugins because their library's behaviour cannot be described purely in terms of types.) Typed Python then ends up looking like a weird Java variant.

If I were going to add a type checker to my Python code again, I'd probably go for Mypy because it seems more like the standard and had marginally better documentation. But right now, I have the Pylance plugin installed in my IDE and that's about it - there's no type checking in CI, I just hope that I catch all the obvious cases with good enough testing. Thankfully the Python side of my work is pretty minimal, a few hundred lines of code at most. If I had a bigger Python project I might revisit this situation, but I'd be more tempted to just avoid Python for bigger projects.


👤 theusus
mypy is the most popular but if you want to use an extension then pyright from MS gave best experience for me.

👤 thayne
I've used mypy for a while, but I've wondered if it is worth switching to pyright, pyre, or pytype.

👤 12_throw_away
There is no perfect solution. However, I actually prefer Pycharm's built-in typechecker, because JetBrains is BY FAR the best at checking syntactically incorrect code, i.e. code that you're in the middle of typing out.

But, Pycharm's still quite limited compared to pyright or even mypy. So I find myself A) doing an extra linting pass with pyright or mypy; and/or B) adding redundant annotations/overloads to help pycharm figure out what's going on.


👤 roland35
I use LazyVim (neovim) and VS Code for Python work. Pyright and Ruff work well with Neovim, and Pylance works only with VS Code (but you need to enable it, if I remember correctly!)

My only issue is I occasionally need to restart Pyright when it fizzes out.


👤 softwaredoug
My rule for these things is to stay close as possible to the mainstream, boring thing, closest to the Python Software Foundation, unless I have an overwhelming reason to switch.

So mypy for me.


👤 pepoluan
I just use the built-in one in PyCharm.

It serves my need, which is to ensure I haven't done mistakes in specifying parameters to functions.

I have no desire making Python to be statically-typed.


👤 breakds
I have been using pyright with lsp in emacs and can recommend.

👤 meitham
The only useful types to add are Cython 3, otherwise adding more letters with no benefit reduces readability and reminds me of “public static void main”.

👤 kelsolaar
Pyright is much faster than Mypy, we changed some times ago and went from something like 20 mins to less than 2.

👤 dlahoda
go with one which does more inference for you. pyright does more, mypy less.

👤 ivalm
I use mypy. We use tox to run pytest, flake8 (linting), and mypy (typing)

👤 bravura
I’ve used mypy for static checking but it’s too fussy.

I enjoy typeguard for dynamic checking using the @typechecked decorator. I haven’t tried beartype, but I know lucidrains uses it.


👤 owenpalmer
Nim