Instrucciones de origen · Vista previa de solo lectura
name
mypy
description
mypy - Static type checker for Python with gradual typing, strict mode, Protocol support, and framework integration
user-invocable
false
disable-model-invocation
true
version
1.0.0
category
toolchain
author
Claude MPM Team
license
MIT
progressive_disclosure
{"entry_point":{"summary":"Static type checker for Python with gradual typing and strict mode","when_to_use":"Adding type safety to Python projects, using type hints in FastAPI/Django, enforcing type checking in CI/CD, refactoring to add type annotations","quick_start":"1. pip install mypy 2. Add type hints to your code 3. mypy your_module.py 4. Create mypy.ini for configuration 5. Use --strict for maximum safety"}}
mypy is the standard static type checker for Python, enabling gradual typing with type hints (PEP 484) and comprehensive type safety. It catches type errors before runtime, improves code documentation, and enhances IDE support while maintaining Python's dynamic nature through incremental adoption.
Key Features:
Gradual typing: Add types incrementally to existing code
Strict mode: Maximum type safety with --strict flag
Type inference: Automatically infer types from context
Protocol support: Structural typing (duck typing with types)
Generic types: TypeVar, Generic, and advanced type patterns
# mypy.ini strict configuration[mypy]strict = True# Relax specific checks if neededdisallow_any_expr = False# Too strict for most projectsdisallow_any_explicit = False# Allow explicit Any
Incremental Adoption Strategies
1. Start with Entry Points
# Start typing from main.py (top-level)# main.pyfrom typing importOptionalfrom app.services import UserService
defmain(config_path: Optional[str] = None) -> None:
"""Application entry point."""
service = UserService()
service.run()
if __name__ == "__main__":
main()
# mypy.ini - Gradually enable strict checking[mypy]# Lenient global defaultsignore_missing_imports = Truedisallow_untyped_defs = False# Strict for new modules[mypy-app.services.user_service]disallow_untyped_defs = Truewarn_return_any = True[mypy-app.api.*]disallow_untyped_defs = Trueno_implicit_optional = True# Still lenient for legacy code[mypy-app.legacy.*]ignore_errors = True
3. Use # type: ignore Strategically
# Suppress specific errors during migrationimport legacy_module # type: ignore[import]defprocess_data(data): # type: ignore[no-untyped-def]# TODO: Add type hintsreturn data.transform()
# Ignore specific error codes
user_dict = get_user_dict()
user_id = user_dict["id"] # type: ignore[index]# Ignore entire line (use sparingly)
result = external_api.call() # type: ignore
4. Reveal Types During Development
from typing import reveal_type
defprocess_user(user_id: int):
user = get_user(user_id)
reveal_type(user) # mypy will show inferred type
name = user.name
reveal_type(name) # mypy will show: str
from typing import Final
# Constants that should never change
API_VERSION: Final = "v1"
MAX_RETRIES: Final[int] = 3# Type error: Cannot assign to final name
API_VERSION = "v2"# Final class (cannot be subclassed)from typing import final
@finalclassBaseConfig:
pass# Type error: Cannot inherit from final classclassAppConfig(BaseConfig): # Error!pass
4. Self Type for Method Chaining
from typing import Self # Python 3.11+classBuilder:
def__init__(self) -> None:
self._value = 0defadd(self, value: int) -> Self:
self._value += value
returnselfdefmultiply(self, value: int) -> Self:
self._value *= value
returnselfdefbuild(self) -> int:
returnself._value
# Type-safe method chaining
result = Builder().add(5).multiply(2).add(3).build()
mypy vs pyright Comparison
Feature Comparison
Feature
mypy
pyright
Type Checker
Official Python type checker
Microsoft's type checker
Speed
Slower on large codebases
Faster, incremental
Strictness
Configurable strict mode
Very strict by default
IDE Integration
Good (LSP support)
Excellent (Pylance in VS Code)
Plugin System
Yes (mypy plugins)
Limited
Error Messages
Clear, detailed
Very detailed, helpful
Community
Large, official
Growing, Microsoft-backed
Type Inference
Good
Excellent
Configuration
mypy.ini, pyproject.toml
pyrightconfig.json, pyproject.toml
When to Use mypy
# Use mypy for:# - Official Python type checking standard# - Plugin ecosystem (Django, SQLAlchemy, Pydantic)# - Gradual typing with fine-grained control# - Compatibility with existing mypy configurations# - CI/CD pipelines (industry standard)
When to Use pyright
# Use pyright for:# - VS Code development (Pylance)# - Faster type checking on large codebases# - Stricter type checking by default# - Better type inference# - Real-time IDE feedback
Relaxed profile (mcp-ticketer): strict flags disabled temporarily with a disable_error_code list for patch releases.
Incremental adoption (mcp-vector-search): ignore_errors = true while stabilizing types.
Missing imports: ignore_missing_imports = true used in mcp-memory and mcp-ticketer.
Reference: see pyproject.toml in edgar, kuzu-memory, mcp-vector-search, and mcp-ticketer.
Best Practices
1. Start with Key Modules
# ✅ GOOD: Type critical business logic first# services/user_service.pyfrom typing importOptionalclassUserService:
defget_user(self, user_id: int) -> Optional[User]:
"""Retrieve user by ID."""returnself.db.query(User).get(user_id)
defcreate_user(self, data: UserCreate) -> User:
"""Create new user."""
user = User(**data.dict())
self.db.add(user)
self.db.commit()
return user
# ✅ GOOD: Explicit types for public APIsdefget_user(user_id: int) -> Optional[User]:
return db.query(User).get(user_id)
# ❌ ACCEPTABLE: Type inference for internal helpersdef_format_name(first, last): # mypy infers str -> strreturnf"{first}{last}"
4. Use reveal_type for Debugging
# During development, check inferred typesfrom typing import reveal_type
defprocess_data(data):
result = transform(data)
reveal_type(result) # mypy: Revealed type is "int"return result * 2
5. Document Type Ignores
# ✅ GOOD: Document why type checking is disabledimport legacy_module # type: ignore[import] # TODO: Add type stubs# ❌ BAD: No explanationimport legacy_module # type: ignore
Common Pitfalls
❌ Anti-Pattern 1: Using Any Everywhere
# WRONG: Defeats purpose of type checkingfrom typing importAnydefprocess(data: Any) -> Any:
return data.transform()
# WRONG: Disables type checking[mypy]ignore_errors = True
Correct:
# Ignore specific modules only[mypy-legacy.*]ignore_errors = True[mypy]strict = True
❌ Anti-Pattern 3: Not Using Optional
# WRONG: Nullable without Optionaldefget_user(user_id: int) -> User:
user = db.get(user_id) # Can be None!return user # Runtime error if None
Correct:
from typing importOptionaldefget_user(user_id: int) -> Optional[User]:
return db.get(user_id)
# Handle None explicitly
user = get_user(123)
if user isnotNone:
print(user.name)
# Common error codes
[attr-defined] # Attribute not defined
[arg-type] # Argument type mismatch
[return-value] # Return type mismatch
[assignment] # Assignment type mismatch
[call-overload] # No matching overload
[index] # Invalid index operation
[operator] # Unsupported operand type
[import] # Cannot find import
[misc] # Miscellaneous type error
[no-untyped-def] # Function missing type annotation
[var-annotated] # Variable needs type annotation