Python Types and Contracts
Overview
Treat type hints as interface design, not decoration.
Focus on explicit contracts, stable public APIs, and boundary-safe modeling.
These are preferred defaults for common cases, not universal rules.
When a default conflicts with project constraints, suggest a better-fit alternative and explain tradeoffs and compensating controls.
When to Use
- Public API signatures lack type annotations or use overly broad types.
- Pydantic models are scattered throughout internal logic instead of at trust boundaries.
- Contract changes risk breaking downstream consumers without migration paths.
- Interfaces accept
Any, object, or untyped dicts where narrower types apply.
- Schema boundaries between layers (API, DB, domain) are implicit or inconsistent.
- Adding or evolving protocols, abstract base classes, or structural subtyping.
When NOT to use:
- Pure implementation-level code with no public interface.
- Throwaway scripts or one-off data munging where type rigor adds no value.
- Performance-critical inner loops where typing overhead matters more than safety.
Quick Reference
- Type public APIs and keep contracts explicit.
- Prefer narrow interfaces and boundary protocols over broad parameter types.
- Use pydantic at trust boundaries by default, not everywhere.
- Make compatibility and migration impact explicit for any contract change.
- Favor
Protocol for structural subtyping over deep inheritance hierarchies.
- Return concrete types from public functions; accept protocols or unions as inputs.
Common Mistakes
- Typing everything identically.
Internal helpers don't need the same rigor as public APIs.
Over-annotating private code adds noise without safety.
- Pydantic everywhere.
Using pydantic models for internal data flow instead of reserving them for validation at trust boundaries (API ingress, config loading, external data).
- Broad return types.
Returning
Any or dict from public functions forces callers to guess structure.
Return concrete types or TypedDicts.
- Breaking contracts silently.
Changing function signatures, removing fields, or narrowing accepted types without versioning, deprecation warnings, or migration notes.
- Ignoring
None.
Omitting Optional or union with None when a value can legitimately be absent, hiding null-safety bugs until runtime.
Scope Note
- Treat these recommendations as preferred defaults for common cases, not universal rules.
- If a default conflicts with project constraints or worsens the outcome, suggest a better-fit alternative and explain why it is better for this case.
- When deviating, call out tradeoffs and compensating controls (tests, observability, migration, rollback).
Invocation Notice
- Inform the user when this skill is being invoked by name:
python-design-modularity.
References
references/typing-policy.md
references/contract-evolution.md
references/pydantic-boundaries.md
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: ahgraber-skills-python-types-contracts3description: Python Types and Contracts4---56# Python Types and Contracts78## Overview910Treat type hints as interface design, not decoration.11Focus on explicit contracts, stable public APIs, and boundary-safe modeling.1213These are preferred defaults for common cases, not universal rules.14When a default conflicts with project constraints, suggest a better-fit alternative and explain tradeoffs and compensating controls.1516## When to Use1718- Public API signatures lack type annotations or use overly broad types.19- Pydantic models are scattered throughout internal logic instead of at trust boundaries.20- Contract changes risk breaking downstream consumers without migration paths.21- Interfaces accept `Any`, `object`, or untyped dicts where narrower types apply.22- Schema boundaries between layers (API, DB, domain) are implicit or inconsistent.23- Adding or evolving protocols, abstract base classes, or structural subtyping.2425**When NOT to use:**2627- Pure implementation-level code with no public interface.28- Throwaway scripts or one-off data munging where type rigor adds no value.29- Performance-critical inner loops where typing overhead matters more than safety.3031## Quick Reference3233- Type public APIs and keep contracts explicit.34- Prefer narrow interfaces and boundary protocols over broad parameter types.35- Use pydantic at trust boundaries by default, not everywhere.36- Make compatibility and migration impact explicit for any contract change.37- Favor `Protocol` for structural subtyping over deep inheritance hierarchies.38- Return concrete types from public functions; accept protocols or unions as inputs.3940## Common Mistakes4142- **Typing everything identically.**43 Internal helpers don't need the same rigor as public APIs.44 Over-annotating private code adds noise without safety.45- **Pydantic everywhere.**46 Using pydantic models for internal data flow instead of reserving them for validation at trust boundaries (API ingress, config loading, external data).47- **Broad return types.**48 Returning `Any` or `dict` from public functions forces callers to guess structure.49 Return concrete types or TypedDicts.50- **Breaking contracts silently.**51 Changing function signatures, removing fields, or narrowing accepted types without versioning, deprecation warnings, or migration notes.52- **Ignoring `None`.**53 Omitting `Optional` or union with `None` when a value can legitimately be absent, hiding null-safety bugs until runtime.5455## Scope Note5657- Treat these recommendations as preferred defaults for common cases, not universal rules.58- If a default conflicts with project constraints or worsens the outcome, suggest a better-fit alternative and explain why it is better for this case.59- When deviating, call out tradeoffs and compensating controls (tests, observability, migration, rollback).6061## Invocation Notice6263- Inform the user when this skill is being invoked by name: `python-design-modularity`.6465## References6667- `references/typing-policy.md`68- `references/contract-evolution.md`69- `references/pydantic-boundaries.md`7071---72> Converted and distributed by [TomeVault](https://tomevault.io/claim/ahgraber) — claim your Tome and manage your conversions.73<!-- tomevault:4.0:skill_md:2026-04-11 -->