← ClaudeAtlas

type-driven-designlisted

Make illegal states unrepresentable — enums instead of boolean and string flags, newtypes instead of bare primitives, parsed types instead of validated ones, typestate for protocol order. Use when a struct has fields that are only valid in some combinations, when validation is re-checked at many call sites, when boolean flags multiply, or when the user asks how to model a domain in Rust.
rewrite-rs/skills · ★ 2 · AI & Automation · score 73
Install: claude install-skill rewrite-rs/skills
# Type-Driven Design A type is a promise about which states exist. This skill changes *what the types allow* — it is the only skill in the Rust bucket that restructures a domain model, and it does so with a stopping rule: encode an invariant in a type when violating it is a real bug class in this codebase, not when it is merely expressible. How a rejection is reported is `/rust-errors`; what a change to a published type costs is `/rust-api-design`. ## The principle A type that cannot represent the bad state removes the runtime check, the test for it, and the bug report about it. Ask of every struct: how many field combinations are constructible, and how many are valid? The gap between those two numbers is the surface where bugs live. ## Enums over flag soup Two booleans make four states; if only three are valid, the fourth is a latent bug: ```rust,ignore // Four states, three valid: is_draft && is_published is nonsense. struct Post { is_draft: bool, is_published: bool, published_at: Option<DateTime<Utc>>, } // Three states, three valid, and published_at cannot go missing. enum Post { Draft { body: String }, Scheduled { body: String, at: DateTime<Utc> }, Published { body: String, at: DateTime<Utc> }, } ``` The same move covers the `Option<T>` pair smell: two `Option` fields where exactly one is always `Some` is an enum with two variants, and the impossible combination — both `None` — stops being constructible. ## Parse, do not validate A funct