Claude
Skills
Sign in
Back

fix-types

Included with Lifetime
$97 forever

Interactively fix any type checking issues in Python code

Code Review

What this skill does


## Your task

To fix types, do the following.

1. First run the type checker to see what the issues are:
    ```
    uv run mypy .
    ```
2. Group the errors you find in to logical buckets.
3. 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.
4. Only once I approve, apply the fix and move onto the next error in the bucket.
5. 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`:

```python
# Preferred - documents the expected type
choices = cast(list[tuple[str, str]], field.choices)

# Avoid when cast is possible - just silences the error
choices = list(field.choices)  # type: ignore[arg-type]
```

**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`:

```python
# Preferred - proper error handling
if obj.related_field is None:
    raise ValueError("Object must have a related field")
result = obj.related_field.some_method()

# Avoid - assertions can be disabled with -O flag
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:

```python
# Good - explains why the ignore is needed
self.tier = tier  # type: ignore[misc]  # mypy can't handle Enum tuple values with custom __init__

# Bad - no explanation
self.tier = tier  # type: ignore[misc]
```

#### 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):

```python
from __future__ import annotations  # Must be the first import

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from django_stubs_ext import StrOrPromise

# Then use StrOrPromise in type hints
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
Files: 1
Size: 3.2 KB
Complexity: 10/100
Category: Code Review

Related in Code Review