mypy and pyright
coreintermediatemypy and pyright are both static type checkers — they read a file's type hints and report type errors without running any code. mypy is the original checker; pyright is Microsoft's, also powering VS Code's Pylance.
Think of it as
A type checker is a proofreader that only checks whether the types promised (int, str, list[User]) are actually consistent throughout the file — it catches "you said this returns a string, but this line returns a number," entirely without running the program.
What we're doing: Run both mypy and pyright on the same real type error and compare their exact output.
- 1
- The return type annotation -> float is what both checkers compare the assignment on line 4 against.
- 4
- result is declared str, but calculate_total returns float — both checkers catch this mismatch, worded differently.
mypy:
typed.py:4: error: Incompatible types in assignment (expression has type "float", variable has type "str") [assignment]
Found 1 error in 1 file (checked 1 source file)
pyright:
typed.py:5:15 - error: Type "float" is not assignable to declared type "str"
"float" is not assignable to "str" (reportAssignmentType)
1 error, 0 warnings, 0 informationsWhy this works: Both checkers catch exactly the same real bug — assigning a float to a str-annotated variable — but format the message differently, use different error-code naming ([assignment] vs. reportAssignmentType), and pyright additionally reports the exact column, not just the line.
Assuming a passing type check means the code has no bugs
Wrong
Better
What you see: A function returns an empty or wrong value while type-checking cleanly, because the annotated shape was technically correct even though the actual implementation is broken.
Why: A type checker only verifies that types are internally consistent — it has no idea whether the VALUES a function actually returns are correct. That is what tests are for; type checking and testing catch different classes of bugs.
- mypy
- Written in Python
- file:line: error: <message> [error-code]
- Checks fully only functions that are already typed
- pyright
- Written in TypeScript — tends to run faster
- file:line:col - error: <message> (reportErrorCode)
- Also powers VS Code's Pylance, live in the editor
Same type error, two checkers' output shape
Together
Remember: mypy and pyright both catch type errors statically, same syntax, different message format — neither replaces real tests.
See also: ruff and flake8 · mypy vs pyright

