type-driven-designlisted
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