← スキル一覧に戻る

type-safety
by ricardoroche
⭐ 0🍴 0📅 2025年11月18日
SKILL.md
name: type-safety description: Automatically applies when writing Python code to enforce comprehensive type hints. Ensures mypy compatibility, proper generic types, and type safety best practices.
Type Safety Pattern Enforcer
All Python code should include comprehensive type hints for better IDE support, documentation, and error catching. This skill enforces type safety best practices and mypy compatibility.
✅ Correct Pattern
from decimal import Decimal
from typing import Any, Dict, List, Optional, Union, TypeVar, Generic
from collections.abc import Callable, Iterable
def process_transaction(
amount: Decimal,
user_id: str,
metadata: Optional[Dict[str, Any]] = None
) -> TransactionResult:
"""Process a transaction with validation."""
if metadata is None:
metadata = {}
# Process transaction
return TransactionResult(
transaction_id="txn_123",
amount=amount,
status="completed"
)
class PaymentService:
"""Service for handling payments."""
api_key: str
base_url: str
timeout: int = 30
def __init__(self, api_key: str, base_url: str, timeout: int = 30) -> None:
"""Initialize payment service."""
self.api_key = api_key
self.base_url = base_url
self.timeout = timeout
async def fetch_user_data(user_id: str) -> UserData:
"""Fetch user data asynchronously."""
# Fetch and return user data
pass
Function Type Hints
# Basic function
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
# Multiple return types
def get_user(user_id: str) -> Optional[User]:
"""Get user by ID, None if not found."""
pass
# No return value
def log_event(event: str) -> None:
"""Log an event."""
print(event)
# Variable arguments
def concatenate(*args: str) -> str:
"""Concatenate strings."""
return "".join(args)
# Keyword arguments
def create_user(**kwargs: Any) -> User:
"""Create user from keyword arguments."""
pass
# Callable type
def apply_operation(
value: int,
operation: Callable[[int], int]
) -> int:
"""Apply operation to value."""
return operation(value)
# Union types (Python 3.10+)
def process(value: int | str) -> str:
"""Process int or string."""
return str(value)
# Union types (pre-3.10)
def process_legacy(value: Union[int, str]) -> str:
"""Process int or string."""
return str(value)
Class Type Hints
from typing import ClassVar
class User:
"""User with type-hinted attributes."""
# Instance attributes
id: str
name: str
email: str
age: Optional[int] = None
# Class variable
default_role: ClassVar[str] = "user"
def __init__(self, id: str, name: str, email: str) -> None:
"""Initialize user."""
self.id = id
self.name = name
self.email = email
def get_display_name(self) -> str:
"""Get display name."""
return self.name
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "User":
"""Create user from dictionary."""
return cls(
id=data["id"],
name=data["name"],
email=data["email"]
)
@staticmethod
def validate_email(email: str) -> bool:
"""Validate email format."""
return "@" in email
Generic Types
from typing import TypeVar, Generic, List, Dict
T = TypeVar('T')
K = TypeVar('K')
V = TypeVar('V')
class Container(Generic[T]):
"""Generic container for any type."""
def __init__(self, item: T) -> None:
"""Initialize with item."""
self.item = item
def get(self) -> T:
"""Get the item."""
return self.item
def set(self, item: T) -> None:
"""Set the item."""
self.item = item
class Cache(Generic[K, V]):
"""Generic key-value cache."""
def __init__(self) -> None:
"""Initialize cache."""
self._data: Dict[K, V] = {}
def get(self, key: K) -> Optional[V]:
"""Get value by key."""
return self._data.get(key)
def set(self, key: K, value: V) -> None:
"""Set key-value pair."""
self._data[key] = value
# Usage
int_container: Container[int] = Container(42)
str_cache: Cache[str, User] = Cache()
Collection Type Hints
# Modern syntax (Python 3.9+)
def process_items(items: list[str]) -> dict[str, int]:
"""Process list of strings."""
return {item: len(item) for item in items}
def aggregate(data: set[int]) -> tuple[int, int]:
"""Get min and max from set."""
return (min(data), max(data))
# Legacy syntax (pre-3.9)
from typing import List, Dict, Set, Tuple
def process_items_legacy(items: List[str]) -> Dict[str, int]:
"""Process list of strings."""
return {item: len(item) for item in items}
# Nested collections
def group_users(users: List[User]) -> Dict[str, List[User]]:
"""Group users by role."""
pass
# Complex types
from typing import Mapping, Sequence, Iterable
def process_mapping(data: Mapping[str, Any]) -> Sequence[str]:
"""Process read-only mapping."""
pass
def process_iterable(items: Iterable[int]) -> list[int]:
"""Process any iterable."""
return list(items)
Optional and None
# Optional (can be None)
def get_user(user_id: str) -> Optional[User]:
"""Get user, None if not found."""
pass
# Explicit None checking
def process_user(user: Optional[User]) -> str:
"""Process user with None check."""
if user is None:
return "No user"
return user.name
# Default None parameter
def create_report(
title: str,
author: Optional[str] = None,
tags: Optional[List[str]] = None
) -> Report:
"""Create report with optional fields."""
if tags is None:
tags = []
return Report(title=title, author=author, tags=tags)
Async Type Hints
import asyncio
from typing import AsyncIterator
async def fetch_data(url: str) -> Dict[str, Any]:
"""Fetch data asynchronously."""
pass
async def fetch_all(urls: List[str]) -> List[Dict[str, Any]]:
"""Fetch multiple URLs."""
tasks = [fetch_data(url) for url in urls]
return await asyncio.gather(*tasks)
async def stream_data() -> AsyncIterator[str]:
"""Stream data asynchronously."""
for i in range(10):
await asyncio.sleep(0.1)
yield f"item-{i}"
# Usage
async def main() -> None:
"""Main async function."""
data = await fetch_data("https://example.com")
async for item in stream_data():
print(item)
Type Narrowing
from typing import Union
def process_value(value: Union[int, str, None]) -> str:
"""Process value with type narrowing."""
if value is None:
return "none"
elif isinstance(value, int):
# Type narrowed to int
return f"int: {value * 2}"
elif isinstance(value, str):
# Type narrowed to str
return f"str: {value.upper()}"
else:
# This should never happen with proper types
raise TypeError(f"Unexpected type: {type(value)}")
def process_user(user: Optional[User]) -> str:
"""Process user with None check."""
if user is None:
return "No user"
# Type narrowed to User (not None)
return user.name
Type Aliases
from typing import TypeAlias, NewType
# Type alias (simple)
UserId: TypeAlias = str
Email: TypeAlias = str
Metadata: TypeAlias = Dict[str, Any]
def get_user(user_id: UserId) -> User:
"""Get user by ID."""
pass
def send_email(email: Email, subject: str) -> None:
"""Send email."""
pass
# NewType (distinct type)
UserId = NewType('UserId', str)
ProductId = NewType('ProductId', str)
def get_user(user_id: UserId) -> User:
"""Get user by ID."""
pass
# These are type-safe
user_id: UserId = UserId("usr_123")
product_id: ProductId = ProductId("prd_456")
# This would be a mypy error:
# get_user(product_id) # Error: Expected UserId, got ProductId
Protocol Types
from typing import Protocol
class Drawable(Protocol):
"""Protocol for drawable objects."""
def draw(self) -> None:
"""Draw the object."""
...
class Circle:
"""Circle class."""
def draw(self) -> None:
"""Draw circle."""
print("Drawing circle")
class Square:
"""Square class."""
def draw(self) -> None:
"""Draw square."""
print("Drawing square")
def render(shape: Drawable) -> None:
"""Render any drawable shape."""
shape.draw()
# Both work with structural typing
render(Circle())
render(Square())
Literal Types
from typing import Literal
def set_status(status: Literal["active", "inactive", "suspended"]) -> None:
"""Set status to specific values only."""
pass
# Valid
set_status("active")
# Invalid (mypy error)
# set_status("unknown")
def process_mode(mode: Literal["read", "write", "append"]) -> None:
"""Process with specific mode."""
if mode == "read":
pass
elif mode == "write":
pass
elif mode == "append":
pass
Type Guards
from typing import TypeGuard
def is_string_list(val: List[Any]) -> TypeGuard[List[str]]:
"""Check if list contains only strings."""
return all(isinstance(item, str) for item in val)
def process_strings(items: List[Any]) -> None:
"""Process list if all items are strings."""
if is_string_list(items):
# Type narrowed to List[str]
for item in items:
print(item.upper()) # Safe, item is str
❌ Anti-Patterns
# ❌ No type hints
def process_data(data): # Missing all type hints
return data
# ✅ Better
def process_data(data: Dict[str, Any]) -> Dict[str, Any]:
return data
# ❌ Using Any everywhere
def process(data: Any) -> Any: # Too generic
pass
# ✅ Better: specific types
def process(data: Dict[str, str]) -> List[str]:
pass
# ❌ Mutable default arguments
def add_item(item: str, items: List[str] = []) -> List[str]:
items.append(item)
return items
# ✅ Better: use None and create new list
def add_item(item: str, items: Optional[List[str]] = None) -> List[str]:
if items is None:
items = []
items.append(item)
return items
# ❌ Not using Optional
def get_user(user_id: str) -> User: # Can return None!
return None # Type error
# ✅ Better
def get_user(user_id: str) -> Optional[User]:
return None # Correct
# ❌ Wrong collection types (pre-3.9)
def process(items: list) -> dict: # Should use List, Dict
pass
# ✅ Better
from typing import List, Dict
def process(items: List[str]) -> Dict[str, int]:
pass
Best Practices Checklist
- ✅ All public functions have type hints
- ✅ All class attributes have type hints
- ✅ Use
Optional[T]for values that can be None - ✅ Use specific types instead of
Anywhen possible - ✅ Use modern syntax (
list[T]) on Python 3.9+ - ✅ Use
Protocolfor structural typing - ✅ Use
TypeAliasfor complex type expressions - ✅ Use
Literalfor fixed string/int values - ✅ Run mypy in strict mode
- ✅ Handle None cases explicitly
- ✅ Use type narrowing with isinstance checks
- ✅ Avoid mutable default arguments
Mypy Configuration
Add to pyproject.toml:
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
Auto-Apply
When writing Python code:
- Add type hints to all function parameters
- Add return type hints to all functions
- Use
Optional[T]for nullable values - Use specific collection types
- Run mypy to verify type safety
- Fix any type errors
References
For comprehensive examples, see:
Related Skills
- pydantic-models - For runtime type validation
- docstring-format - For documenting types
- async-await-checker - For async type hints
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です