Skip to main content

What is Mypy, How to Use It, and Why It Matters

· 3 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

Python is known for being a dynamically typed language — you don’t have to declare variable types, and everything works at runtime. But as your codebase grows, undetected type errors can creep in. That’s where Mypy comes in.

Mypy is a static type checker for Python. It checks your Python code for type errors without running it.


Why Use Mypy?

  • ✅ Detect bugs early (before running the code)
  • ✅ Improve code quality and readability
  • ✅ Easier refactoring and debugging
  • ✅ Helps IDEs with better autocomplete and hints
  • ✅ Integrates smoothly into CI/CD workflows

You might’ve seen Mypy mentioned in our Shift Left Paradigm article, where it plays a key role in early-stage static analysis.


Installing Mypy

pip install mypy

First Example: Catching a Type Error

def greet(name: str) -> str:
return "Hello " + name

print(greet(42)) # 😬 Works at runtime but wrong type!

Run Mypy:

mypy script.py

Mypy will warn you:

error: Argument 1 to "greet" has incompatible type "int"; expected "str"

Example: Catching Missing Return Types

def add(x: int, y: int):
return x + y

Mypy can infer the return type but warns you if you’ve set strict rules for missing annotations. It encourages explicit typing:

def add(x: int, y: int) -> int:
return x + y

Advanced Typing: Union, Optional, List

from typing import Union, Optional, List

def get_price(code: Union[str, int]) -> Optional[float]:
if isinstance(code, str):
return 9.99
return None

Mypy handles all of this. If you accidentally do:

price: float = get_price("A123")

It will warn:

error: Incompatible types in assignment (expression has type "Optional[float]", variable has type "float")

Using Mypy with Classes

class User:
def __init__(self, id: int, name: str) -> None:
self.id = id
self.name = name

def get_username(user: User) -> str:
return user.name

This ensures that you never accidentally pass a dictionary instead of a User instance.


How Mypy Helps Refactoring

If you refactor a large project and rename a class or function signature, Mypy will catch all related type mismatches before you even run the tests.


Strict Mode: Safer, Cleaner Code

Enable strict mode in mypy.ini or pyproject.toml:

[mypy]
strict = True
disallow_untyped_defs = True
warn_unused_ignores = True

Integration with CI/CD

You can add Mypy to your GitHub Actions or GitLab CI pipeline to automatically reject PRs with type errors.


Combining Mypy with Tools like pyright and ruff

  • pyright: A faster alternative with better TypeScript-like checking
  • ruff: A linter that complements Mypy for overall code style enforcement

Limitations of Mypy

  • Runtime behavior still rules — Mypy only helps pre-runtime
  • Some dynamic Python tricks (e.g., monkey patching) may confuse Mypy
  • You must annotate — which may feel verbose for very small scripts

Conclusion

Mypy is a powerful tool that helps Python developers shift left — detecting bugs before they ship. It enforces clean design, improves developer experience, and is a must-have in any professional Python codebase.


Further Reading