Making Invalid States Unrepresentable
Workflow A: Review Existing Code
- Identify the scope (module, file, type, or function under review).
- Read the code and enumerate the types, fields, and state representations.
- Detect anti-patterns (see checklist below).
- For each finding, propose a concrete refactoring using the appropriate technique from
references/.
- Assess tradeoffs — see
references/advanced-topics.md § Tradeoffs.
- Present findings as a prioritized list: high-value (core domain, security, APIs) first.
Workflow B: Design New Types
- Collect domain requirements: valid states, invalid states, transitions.
- Choose modeling techniques — read
references/core-and-parse.md for foundational approach.
- Model with types: sum types for alternatives, product types for combinations, phantom/branded types for compile-time tags.
- Push validation to boundaries: parse external input immediately into precise types.
- Validate the design: confirm invalid states cannot be constructed.
- Iterate as domain understanding deepens.
Anti-Pattern Detection Checklist
Flag code that exhibits any of these — see references/anti-patterns-and-examples.md for details and fixes:
Technique Selection Guide
| Situation |
Technique |
Reference |
| Mutually exclusive states |
Sum types / discriminated unions |
references/techniques-structural.md § 1 |
| Domain-constrained primitives |
Newtype + smart constructor |
references/techniques-structural.md § 2 |
| State machine / workflow |
Typestate pattern |
references/techniques-structural.md § 3 |
| Collection must be non-empty |
NonEmpty collection |
references/techniques-structural.md § 4 |
| Prevent argument swaps |
Branded / opaque types |
references/techniques-type-level.md § 5 |
| Compile-time state tagging |
Phantom types |
references/techniques-type-level.md § 6 |
| Required fields enforcement |
Type-safe builder |
references/techniques-type-level.md § 7 |
| Complex numeric/range invariants |
Refinement types |
references/techniques-type-level.md § 8 |
Core Principle (Summary)
Design types so invalid states cannot be constructed. Let the compiler enforce correctness. Parse at boundaries, trust types internally. See references/core-and-parse.md.
Output Format
When reviewing code, present each finding as:
- Location — file, line, type/function
- Anti-pattern — which pattern from the checklist
- Risk — what invalid state is possible
- Recommendation — specific technique and refactored type signature
- Priority — high (core domain/security/API), medium, low
When designing types, present:
- Domain states — enumerated valid and invalid states
- Type definitions — concrete code in the user's language
- Boundary parsers — constructors/factories that validate at entry points
- Tradeoff notes — where pragmatism overrides purity
References
references/core-and-parse.md — Core principle and parse-don't-validate pattern
references/techniques-structural.md — Sum types, newtypes, typestate, NonEmpty
references/techniques-type-level.md — Branded types, phantom types, builders, refinement types
references/anti-patterns-and-examples.md — Anti-patterns to detect and real-world examples
references/implementation-guide.md — Step-by-step process, code review checklist, language support, related principles
references/advanced-topics.md — Advanced techniques, modern applications, industry trends, tradeoffs, resources
1---2name: making-invalid-states-unrepresentable3description: Analyzes existing code and guides new type design to make invalid states unrepresentable using type system techniques such as sum types, newtypes, typestate, branded types, and parse-don't-validate. Use when reviewing code for invalid-state bugs, refactoring types to eliminate impossible states, designing domain models, or applying compile-time correctness patterns. Language-agnostic.4---56# Making Invalid States Unrepresentable78## Workflow A: Review Existing Code9101. Identify the scope (module, file, type, or function under review).112. Read the code and enumerate the types, fields, and state representations.123. Detect anti-patterns (see checklist below).134. For each finding, propose a concrete refactoring using the appropriate technique from `references/`.145. Assess tradeoffs — see `references/advanced-topics.md` § Tradeoffs.156. Present findings as a prioritized list: high-value (core domain, security, APIs) first.1617## Workflow B: Design New Types18191. Collect domain requirements: valid states, invalid states, transitions.202. Choose modeling techniques — read `references/core-and-parse.md` for foundational approach.213. Model with types: sum types for alternatives, product types for combinations, phantom/branded types for compile-time tags.224. Push validation to boundaries: parse external input immediately into precise types.235. Validate the design: confirm invalid states cannot be constructed.246. Iterate as domain understanding deepens.2526## Anti-Pattern Detection Checklist2728Flag code that exhibits any of these — see `references/anti-patterns-and-examples.md` for details and fixes:2930- [ ] **Primitive obsession** — raw strings/ints used for domain concepts (IDs, emails, money)31- [ ] **Boolean blindness** — booleans that lose context about what was verified32- [ ] **Optional property proliferation** — many optional fields instead of a union type33- [ ] **Stringly-typed code** — open strings where a closed set of literals applies34- [ ] **Shotgun parsing** — same validation repeated in multiple call sites35- [ ] **Boolean soup** — multiple booleans encoding what should be a state machine36- [ ] **Unguarded constructors** — types with invariants that can be constructed without validation3738## Technique Selection Guide3940| Situation | Technique | Reference |41|-----------|-----------|-----------|42| Mutually exclusive states | Sum types / discriminated unions | `references/techniques-structural.md` § 1 |43| Domain-constrained primitives | Newtype + smart constructor | `references/techniques-structural.md` § 2 |44| State machine / workflow | Typestate pattern | `references/techniques-structural.md` § 3 |45| Collection must be non-empty | NonEmpty collection | `references/techniques-structural.md` § 4 |46| Prevent argument swaps | Branded / opaque types | `references/techniques-type-level.md` § 5 |47| Compile-time state tagging | Phantom types | `references/techniques-type-level.md` § 6 |48| Required fields enforcement | Type-safe builder | `references/techniques-type-level.md` § 7 |49| Complex numeric/range invariants | Refinement types | `references/techniques-type-level.md` § 8 |5051## Core Principle (Summary)5253Design types so invalid states **cannot be constructed**. Let the compiler enforce correctness. Parse at boundaries, trust types internally. See `references/core-and-parse.md`.5455## Output Format5657When reviewing code, present each finding as:58591. **Location** — file, line, type/function602. **Anti-pattern** — which pattern from the checklist613. **Risk** — what invalid state is possible624. **Recommendation** — specific technique and refactored type signature635. **Priority** — high (core domain/security/API), medium, low6465When designing types, present:66671. **Domain states** — enumerated valid and invalid states682. **Type definitions** — concrete code in the user's language693. **Boundary parsers** — constructors/factories that validate at entry points704. **Tradeoff notes** — where pragmatism overrides purity7172## References7374- `references/core-and-parse.md` — Core principle and parse-don't-validate pattern75- `references/techniques-structural.md` — Sum types, newtypes, typestate, NonEmpty76- `references/techniques-type-level.md` — Branded types, phantom types, builders, refinement types77- `references/anti-patterns-and-examples.md` — Anti-patterns to detect and real-world examples78- `references/implementation-guide.md` — Step-by-step process, code review checklist, language support, related principles79- `references/advanced-topics.md` — Advanced techniques, modern applications, industry trends, tradeoffs, resources