| name | fix-types |
| description | Interactively fix any type checking issues in Python code |
| allowed-tools | ["Bash(uv run mypy *)"] |
Your task
To fix types, do the following.
- First run the type checker to see what the issues are:
uv run mypy .
- Group the errors you find in to logical buckets.
- For each bucket of errors, go through the errors one at a time, tell me the fix you want to apply, and then ask if
I have any questions or suggestions before proceeding.
- Only once I approve, apply the fix and move onto the next error in the bucket.
- Once you've completed a bucket, ask me if I'd like to move on to the next bucket.
Prefer cast() over type: ignore
When mypy can't infer the correct type, prefer using cast() over # type: ignore:
choices = cast(list[tuple[str, str]], field.choices)
choices = list(field.choices)
Why: cast() explicitly documents what type you expect, making the code more readable and maintainable. It also doesn't silence other potential errors on the same line.
Prefer proper errors over assertions for null checks
When adding null checks to satisfy mypy, prefer raising proper exceptions over using assert:
if obj.related_field is None:
raise ValueError("Object must have a related field")
result = obj.related_field.some_method()
assert obj.related_field is not None
result = obj.related_field.some_method()
Why: Assertions can be disabled in production with python -O, making them unreliable for runtime validation. Proper exceptions ensure the check always runs and provides better error handling.
When using type: ignore, add a comment
If type: ignore is necessary (e.g., mypy limitation with valid code), always add a short explanation:
self.tier = tier
self.tier = tier
Type Hints for Django Lazy Translation Strings
When using type hints with Django's lazy translation strings (gettext_lazy), use the following pattern to avoid mypy errors while keeping the code working in production (where django-stubs-ext is not installed):
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from django_stubs_ext import StrOrPromise
def my_function(name: StrOrPromise) -> StrOrPromise:
...
class MyData:
title: StrOrPromise
description: StrOrPromise
Why this pattern:
from __future__ import annotations makes type annotations strings at runtime (not evaluated)
if TYPE_CHECKING: ensures the import only happens during type checking, not at runtime
django-stubs-ext is a dev dependency and won't be available in production
- This pattern allows both regular strings and lazy translation strings to be accepted