Skip to content
Development
Skill

/m05-type-driven

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, 类型状态, 新类型模式, 类型驱动设计

From plugin
rust-skills
1.4k38 skills11 agents21 commands1 hook
+1
Install
$ npx -y skills add zhanghandong/rust-skills --skill m05-type-driven --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/m05-type-driven

Context preview

The summary Claude sees to decide when to auto-load this skill.

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, 类型状态, 新类型模式, 类型驱动设计

SKILL.md

m05-type-driven.SKILL.md
name: m05-type-driven
description: "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

struct 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

struct 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 |

Read more
Ships withrust-skills

AI-powered Rust development assistant with meta-cognition framework

Get the whole plugin

Other skills on rust-skills.