← Back to list

python-type-hints
by jsmithdenverdev
OpenCode configuration
⭐ 0🍴 0📅 Jan 21, 2026
SKILL.md
name: python-type-hints description: Type annotations, static typing with mypy, generic types, protocols license: MIT compatibility: opencode metadata: audience: python-developers focus: typing
What I do
I provide guidance on type hints and static typing in Python, including:
- Basic type hints (list, dict, tuple, Optional, Union)
- Type unions and intersection types (Literal, TypeGuard)
- Generic types and TypeVar
- Protocol types (structural subtyping)
- Self types and recursive types
- Callable and function types
- mypy configuration and strict mode
- Type narrowing and isinstance checks
- Type stub files for third-party libraries
When to use me
Use me when:
- Adding type hints to existing code
- Designing type-safe APIs
- Configuring mypy for a project
- Working with generic types
- Creating type guards and type predicates
- Writing type stub files
- Debugging type checking errors
- Implementing protocols for duck typing
- Designing self-referential types
Best Practices
✅ Basic Type Hints
from typing import Optional, Union, Literal
from pathlib import Path
def process_file(
path: Path,
encoding: Optional[str] = None,
mode: Literal["read", "write"] = "read"
) -> Union[str, bytes]:
"""Process a file with proper type hints."""
if mode == "read":
return path.read_text(encoding or "utf-8")
else:
return path.read_bytes()
✅ Use Modern Union Syntax (Python 3.10+)
# Python 3.10+ union syntax
def process_value(value: str | int | float) -> str:
"""Process value using modern union syntax."""
return str(value)
# Equivalent to old syntax (Python < 3.10)
from typing import Union
def process_value(value: Union[str, int, float]) -> str:
"""Process value using old union syntax."""
return str(value)
✅ Use TypeGuard for Type Narrowing
from typing import Protocol, TypeGuard
class SupportsRead(Protocol):
"""Protocol for readable objects."""
def read(self, size: int = -1) -> bytes: ...
def is_binary_data(obj: object) -> TypeGuard[SupportsRead]:
"""Type guard for binary data objects."""
return isinstance(obj, (bytes, bytearray, SupportsRead))
def process_data(data: SupportsRead | str) -> bytes:
"""Process data with type narrowing."""
if is_binary_data(data):
return data.read()
return data.encode()
✅ Use Protocols for Structural Subtyping
from typing import Protocol, runtime_checkable
@runtime_checkable
class Drawable(Protocol):
"""Protocol for drawable objects."""
def draw(self) -> None: ...
def render(objects: list[Drawable]) -> None:
"""Render all drawable objects."""
for obj in objects:
obj.draw()
# Usage with runtime checking
class Circle:
def draw(self) -> None:
print("Drawing circle")
def can_draw(obj: object) -> bool:
"""Check if object is drawable."""
return isinstance(obj, Drawable)
✅ Generic Types with TypeVar
from typing import TypeVar, Generic
T = TypeVar("T")
class Container(Generic[T]):
"""Generic container for any type."""
def __init__(self, value: T) -> None:
self.value = value
def get(self) -> T:
"""Get the stored value."""
return self.value
# Bounded TypeVar
class Animal:
pass
class Dog(Animal):
pass
A = TypeVar("A", bound=Animal)
def adopt(pet: A) -> A:
"""Adopt an animal."""
return pet
# Usage
container_int = Container(42)
container_str = Container("hello")
✅ Self Types for Fluent Interfaces
from typing import Self
class Builder:
"""Builder pattern with Self type."""
def __init__(self) -> None:
self.items: list[str] = []
def add_item(self, item: str) -> Self:
"""Add an item and return self for chaining."""
self.items.append(item)
return self
def build(self) -> list[str]:
"""Build and return the list."""
return self.items
# Usage
result = Builder().add_item("a").add_item("b").build()
✅ Callable Types
from typing import Callable
def apply_function(
func: Callable[[int, int], int],
a: int,
b: int
) -> int:
"""Apply a function to two integers."""
return func(a, b)
# With variable arguments
def process_data(
processor: Callable[..., str],
*args: object
) -> str:
"""Process data with a callable."""
return processor(*args)
✅ Type Stubs for Third-Party Libraries
# mymodule_stubs.pyi
# Type stub file for mymodule
from typing import List, Optional
def process_items(items: List[str]) -> Optional[dict]:
"""Process items and return optional dict."""
...
class DataProcessor:
"""Data processor class."""
def __init__(self, config: dict) -> None: ...
def run(self) -> None: ...
✅ ParamSpec and Concatenate (Python 3.10+)
from typing import ParamSpec, Concatenate
P = ParamSpec("P")
def decorator(
func: Callable[Concatenate[int, P], int]
) -> Callable[P, int]:
"""Decorator with parameter specification."""
def wrapper(*args: P.args, **kwargs: P.kwargs) -> int:
return func(42, *args, **kwargs)
return wrapper
@decorator
def multiply(x: int, y: int) -> int:
"""Multiply two numbers."""
return x * y
Type Narrowing
✅ Use isinstance for Type Narrowing
def process(value: int | str | list[str]) -> str:
"""Process value with type narrowing."""
if isinstance(value, int):
return f"Number: {value}"
elif isinstance(value, str):
return f"String: {value}"
else:
# value is list[str] here
return f"List: {', '.join(value)}"
✅ Use Literal for Precise Values
from typing import Literal
def set_status(status: Literal["pending", "active", "completed"]) -> None:
"""Set status to one of the literal values."""
pass
# Works
set_status("active")
# Type error (mypy catches this)
set_status("invalid")
Mypy Configuration
✅ Setup mypy for Your Project
# mypy.ini or setup.cfg
[mypy]
python_version = 3.11
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
disallow_any_generics = True
check_untyped_defs = True
no_implicit_optional = True
warn_redundant_casts = True
warn_unused_ignores = True
warn_unreachable = True
strict_equality = True
[pytest]
ignore_missing_imports = True
[tests]
no_warn_unused_ignores = True
✅ Use Type Comments for Legacy Code
# Type comments for Python 3.5-3.8 compatibility
def calculate_total(x, y):
# type: (int, float) -> float
"""Calculate total with type comments."""
return x + y
Common Pitfalls
❌ Don't Use Optional When Value is Required
# BAD: Optional when value is always present
def get_user_id(user_id: Optional[int]) -> int:
if user_id is None:
raise ValueError("user_id required")
return user_id
# GOOD: Use non-optional type
def get_user_id(user_id: int) -> int:
return user_id
❌ Don't Overuse Any
# BAD: Any hides type errors
def process_data(data: Any) -> Any:
return data.process()
# GOOD: Use specific type or Protocol
def process_data(data: SupportsProcess) -> Result:
return data.process()
❌ Don't Ignore Type Errors
# BAD: Silencing type errors without reason
def complex_function(x: int, y: str) -> dict: # type: ignore
return {"result": x + int(y)}
# GOOD: Fix the type error or explain the ignore
def complex_function(x: int, y: str) -> dict[str, int]:
return {"result": x + int(y)}
Advanced Type Patterns
✅ Recursive Types
from typing import Union, TypedDict
class Node(TypedDict):
"""Recursive tree node."""
value: int
left: Union["Node", None]
right: Union["Node", None]
def sum_tree(node: Union[Node, None]) -> int:
"""Sum all values in tree."""
if node is None:
return 0
return node["value"] + sum_tree(node["left"]) + sum_tree(node["right"])
✅ TypedDict for Dictionary Structure
from typing import TypedDict, Required, NotRequired
class User(TypedDict):
"""User structure definition."""
id: Required[int]
name: Required[str]
email: Required[str]
age: NotRequired[int]
def process_user(user: User) -> None:
"""Process user with guaranteed structure."""
print(f"User: {user['name']} ({user['email']})")
Type Checking Workflow
- Enable mypy in CI/CD
- Run mypy before committing (pre-commit hook)
- Fix type errors incrementally
- Use
# type: ignoresparingly and document why - Add stub files for untyped dependencies
- Keep type hints up to date when changing code
- Use strict mode for new code
References
- PEP 484 (Type Hints): https://peps.python.org/pep-0484/
- PEP 585 (Type Hinting Generics): https://peps.python.org/pep-0585/
- PEP 604 (Allow writing union types as X | Y): https://peps.python.org/pep-0604/
- PEP 673 (Self Type): https://peps.python.org/pep-0673/
- PEP 646 (Variadic Generics): https://peps.python.org/pep-0646/
- mypy documentation: https://mypy.readthedocs.io/
- Python typing module: https://docs.python.org/3/library/typing.html
Score
Total Score
50/100
Based on repository quality metrics
✓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
Reviews
💬
Reviews coming soon