Guides type-driven design in Rust, using types to make invalid states unrepresentable.
- What it does
- This skill provides guidance on type-driven design, covering patterns such as newtypes, type state, PhantomData, marker traits, builders, sealed traits, and zero-sized types. It frames design as a question of how the type system can prevent invalid states, with error-to-design prompts, decision tables, and anti-pattern comparisons. It also points to related skills for domain modeling, trait design, error handling, and anti-patterns.
- When to use it
- Use it when designing types or APIs where compile-time validation is preferable to runtime checks, such as encoding invariants, modeling state machines, or wrapping primitives for type safety. It is also useful when deciding between newtypes, type state, builders, or marker traits.
- Requirements
- No tools, packages, or runtime beyond the agent; it is instructions only and ships no scripts.
Type-Driven Design
Layer 1: Language Mechanics
Core Question
How can the type system prevent invalid states?
Before reaching for runtime checks:
- Can the compiler catch this error?
- Can invalid states be unrepresentable?
- Can the type encode the invariant?
Error → Design Question
Thinking Prompt
Before adding runtime validation:
-
Can the type encode the constraint?
- Numeric range → bounded types or newtypes
- Valid states → type state pattern
- Semantic meaning → newtype
-
When is validation possible?
- At construction → validated newtype
- At state transition → type state
- Only at runtime → Result with clear error
-
Who needs to know the invariant?
- Compiler → type-level encoding
- API users → clear type signatures
- Runtime only → documentation
Trace Up ↑
When type design is unclear:
Trace Down ↓
From design to implementation:
Quick Reference
Pattern Examples
Newtype
Type State
Decision Guide
Anti-Patterns
Related Skills