Skip to content
Back to skills

Typing Patterns

ASecurity

Python type annotation patterns without `type: ignore`. Always the correct solution.

  • 4 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 26, 2026
developmentpythongodocumentation

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add ruslan-korneev/claude-plugins --skill typing-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typing Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Typing Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ruslan-korneev-typing-patterns/badge)](https://www.skillsdirectory.com/skills/ruslan-korneev-typing-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Python Typing Patterns

Python type annotation patterns without `type: ignore`. Always the correct solution.

## Triggers

Use this skill when the user:
- Gets mypy/pyright errors
- Asks about Python type annotations
- Wants to add type hints
- Works with generics, protocols, TypeVar

## Main Principle: NEVER type: ignore

Every type error has a correct solution. `type: ignore` is:
- Masking potential bugs
- Disabling type checking
- Technical debt

More details: `${CLAUDE_PLUGIN_ROOT}/skills/typing-patterns/references/why-no-type-ignore.md`

## Dictionary Typing — TypedDict Instead of dict

More details: `${CLAUDE_PLUGIN_ROOT}/skills/typing-patterns/references/dict-typing.md`

```python
# Bad: Weak level
def process(data: dict): ...

# Warning: Medium level
def process(data: dict[str, Any]): ...

# Good: Strong level
class UserData(TypedDict):
    id: int
    email: str
    name: str

def process(data: UserData): ...
```

**Why TypedDict is better:**
- Key checking at compile time (`data["emial"]` → error)
- Value type checking
- IDE autocomplete
- Data structure documentation

**When `dict[K, V]` is acceptable:**
- Homogeneous collections: `dict[str, User]`, `dict[int, float]`
- Caches, counters, ID → object mappings

## Basic Types (Python 3.10+)

```python
# Primitives
x: int = 1
y: str = "hello"
z: bool = True
f: float = 1.5

# Collections (built-in)
items: list[str] = ["a", "b"]
mapping: dict[str, int] = {"a": 1}
unique: set[int] = {1, 2, 3}
pair: tuple[int, str] = (1, "a")

# Union (Python 3.10+)
value: int | str = 1
optional: str | None = None

# Callable
from collections.abc import Callable
handler: Callable[[int, str], bool] = lambda x, s: True
```

## Generics

More details: `${CLAUDE_PLUGIN_ROOT}/skills/typing-patterns/references/generics.md`

```python
from typing import TypeVar, Generic

T = TypeVar("T")
K = TypeVar("K")
V = TypeVar("V")


class Repository(Generic[T]):
    def get(self, id: int) -> T | None: ...
    def save(self, item: T) -> T: ...


# Usage
class UserRepository(Repository[User]):
    pass


# Python 3.12+ syntax
class Repository[T]:
    def get(self, id: int) -> T | None: ...
```

## Protocols

```python
from typing import Protocol


class Readable(Protocol):
    def read(self) -> str: ...


class Writable(Protocol):
    def write(self, data: str) -> None: ...


# Structural subtyping — no explicit inherit needed
class MyFile:
    def read(self) -> str:
        return "content"


def process(source: Readable) -> str:
    return source.read()


process(MyFile())  # OK — MyFile implements Readable
```

## TypeVar with Constraints

```python
from typing import TypeVar

# Bound — only subtypes
T = TypeVar("T", bound=BaseModel)

def validate(model: T) -> T:
    # model is guaranteed to have BaseModel methods
    return model


# Constraints — only specific types
S = TypeVar("S", str, bytes)

def process(data: S) -> S:
    # data is either str or bytes
    return data
```

## Overload

```python
from typing import overload


@overload
def process(x: int) -> int: ...


@overload
def process(x: str) -> str: ...


def process(x: int | str) -> int | str:
    if isinstance(x, int):
        return x * 2
    return x.upper()
```

## TypeGuard

```python
from typing import TypeGuard


def is_string_list(val: list[object]) -> TypeGuard[list[str]]:
    return all(isinstance(x, str) for x in val)


items: list[object] = ["a", "b", "c"]
if is_string_list(items):
    # mypy knows: items is list[str]
    print(items[0].upper())
```

## Common Error Solutions

### Optional Without Check

```python
# Bad
def get_name(user: User | None) -> str:
    return user.name  # Error: Item "None" has no attribute "name"

# Good
def get_name(user: User | None) -> str:
    if user is None:
        raise ValueError("User is required")
    return user.name
```

### Missing Return Type

```python
# Bad
def process(x):
    return x * 2

# Good
def process(x: int) -> int:
    return x * 2
```

### list Without Type

```python
# Bad
items = []  # Need type annotation

# Good
items: list[str] = []
```

### Callable Types

```python
# Bad
def register(callback):
    ...

# Good
from collections.abc import Callable

def register(callback: Callable[[int], str]) -> None:
    ...

# Or with ParamSpec for exact signature passing
from typing import ParamSpec, TypeVar

P = ParamSpec("P")
R = TypeVar("R")

def decorator(func: Callable[P, R]) -> Callable[P, R]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        return func(*args, **kwargs)
    return wrapper
```

## Configuration

### mypy (strict)

```toml
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_untyped_calls = true
```

### pyright

```json
{
  "typeCheckingMode": "strict",
  "pythonVersion": "3.12"
}
```

## Plugin Commands

- `/types:check [path]` — check types
- `/types:explain <error>` — explain error + solution

Files in this skill

  • SKILL.md4.9 KB
  • references/dict-typing.md5.6 KB
  • references/generics.md5.2 KB
  • references/why-no-type-ignore.md4.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.