Claude Agent Skill · by Zhanghandong

M05 Type Driven

The m05-type-driven skill teaches developers how to use Rust's type system to prevent invalid states and encode invariants at compile time rather than relying o

Install
Terminal · npx
$npx skills add https://github.com/zhanghandong/rust-skills --skill m05-type-driven
Works with Paperclip

How M05 Type Driven fits into a Paperclip company.

M05 Type Driven drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md175 lines
Expand
---name: m05-type-drivendescription: "CRITICAL: Use for type-driven design. Triggers: type state, PhantomData, newtype, marker trait, builder pattern, make invalid states unrepresentable, compile-time validation, sealed trait, ZST, 类型状态, 新类型模式, 类型驱动设计"user-invocable: false--- # 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 | Pattern | Don't Just Say | Ask Instead ||---------|----------------|-------------|| Primitive obsession | "It's just a string" | What does this value represent? || Boolean flags | "Add an is_valid flag" | Can states be types? || Optional everywhere | "Check for None" | Is absence really possible? || Validation at runtime | "Return Err if invalid" | Can we validate at construction? | --- ## Thinking Prompt Before adding runtime validation: 1. **Can the type encode the constraint?**   - Numeric range → bounded types or newtypes   - Valid states → type state pattern   - Semantic meaning → newtype 2. **When is validation possible?**   - At construction → validated newtype   - At state transition → type state   - Only at runtime → Result with clear error 3. **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: ```"Need to validate email format"    ↑ Ask: Is this a domain value object?    ↑ Check: m09-domain (Email as Value Object)    ↑ Check: domain-* (validation requirements)``` | Situation | Trace To | Question ||-----------|----------|----------|| What types to create | m09-domain | What's the domain model? || State machine design | m09-domain | What are valid transitions? || Marker trait usage | m04-zero-cost | Static or dynamic dispatch? | --- ## Trace Down ↓ From design to implementation: ```"Need type-safe wrapper for primitives"    ↓ Newtype: struct UserId(u64); "Need compile-time state validation"    ↓ Type State: Connection<Connected> "Need to track phantom type parameters"    ↓ PhantomData: PhantomData<T> "Need capability markers"    ↓ Marker Trait: trait Validated {} "Need gradual construction"    ↓ Builder: Builder::new().field(x).build()``` --- ## Quick Reference | Pattern | Purpose | Example ||---------|---------|---------|| Newtype | Type safety | `struct UserId(u64);` || Type State | State machine | `Connection<Connected>` || PhantomData | Variance/lifetime | `PhantomData<&'a T>` || Marker Trait | Capability flag | `trait Validated {}` || Builder | Gradual construction | `Builder::new().name("x").build()` || Sealed Trait | Prevent external impl | `mod private { pub trait Sealed {} }` | ## Pattern Examples ### Newtype ```ruststruct Email(String);  // Not just any string impl Email {    pub fn new(s: &str) -> Result<Self, ValidationError> {        // Validate once, trust forever        validate_email(s)?;        Ok(Self(s.to_string()))    }}``` ### Type State ```ruststruct Connection<State>(TcpStream, PhantomData<State>); struct Disconnected;struct Connected;struct Authenticated; impl Connection<Disconnected> {    fn connect(self) -> Connection<Connected> { ... }} impl Connection<Connected> {    fn authenticate(self) -> Connection<Authenticated> { ... }}``` --- ## Decision Guide | Need | Pattern ||------|---------|| Type safety for primitives | Newtype || Compile-time state validation | Type State || Lifetime/variance markers | PhantomData || Capability flags | Marker Trait || Gradual construction | Builder || Closed set of impls | Sealed Trait || Zero-sized type marker | ZST struct | --- ## Anti-Patterns | Anti-Pattern | Why Bad | Better ||--------------|---------|--------|| Boolean flags for states | Runtime errors | Type state || String for semantic types | No type safety | Newtype || Option for uninitialized | Unclear invariant | Builder || Public fields with invariants | Invariant violation | Private + validated new() | --- ## Related Skills | When | See ||------|-----|| Domain modeling | m09-domain || Trait design | m04-zero-cost || Error handling in constructors | m06-error-handling || Anti-patterns | m15-anti-pattern |