Swift Type-Driven Design
Use this skill to design Swift models that encode business rules in types so invalid states are hard or impossible to represent.
Agent behavior contract
- Model domain concepts first, implementation details second.
- Prefer value semantics (
struct,enum) unless reference identity is required. - Replace primitive obsession with strong domain types only when it captures an essential invariant.
- Use "parse, do not validate": create validated values once, then pass validated types through the system.
- Favor compile-time guarantees over runtime checks.
- Keep changes incremental and local to the workflow being modeled.
- If introducing wrappers, improve call-site clarity, not just type novelty.
Quick decision tree
-
Need the mental model and core principles?
- Read
references/modeling-playbook.md"Foundations" - Deep source: Fundamentals of type-driven code (
references/fundamentals-of-type-driven-code.md)
- Read
-
Need safer user input or request payloads?
- Read
references/pattern-catalog.md"Validation-carrying types" - Deep source: Type-safe validation (
references/type-safe-validation.md)
- Read
-
Need compile-time gated access to a feature or workflow step?
- Read
references/pattern-catalog.md"Witness pattern" - Deep source: Witness pattern: type-safe access control (
references/witness-pattern-type-safe-access-control.md)
- Read
-
Need to model a domain with product/sum types and clear naming?
- Read
references/modeling-playbook.md"Domain modeling flow" - Deep source: Domain modeling with types (
references/domain-modeling-with-types.md)
- Read
-
Need to remove impossible states from existing models?
- Read
references/pattern-catalog.md"Illegal-state elimination" - Deep source: Making illegal states unrepresentable (
references/making-illegal-states-unrepresentable.md)
- Read
Operating workflow
When asked to model or refactor:
- Identify domain invariants and preconditions in plain language.
- Classify each concept:
- Primitive domain type
- Product type (AND)
- Sum type (OR)
- Witness/precondition type
- Choose the smallest type change that encodes the invariant.
- Move checks to type construction boundaries.
- Update downstream APIs to consume strong types instead of raw primitives.
- Remove redundant runtime validation that the type now guarantees.
Modeling heuristics
- Start with
struct. - Use
enumfor mutually exclusive states. - Use nested
IDtypes to avoid cross-entity identifier mixups. - Avoid boolean gates for access control when a witness can model it.
- Avoid
String/Intin public domain APIs when semantic meaning matters. - Keep optional use intentional; each
Optionalintroduces anonestate.
Anti-patterns to avoid
- Validation scattered across call sites.
- Re-checking invariants that should be proven by type construction.
- "Two optionals" used to model a choice with illegal combinations.
- Feature gating with plain
Boolacross many entry points. - Premature wrappers with no encoded invariant or semantic benefit.
Reference files
references/_index.md- quick navigation by problemreferences/modeling-playbook.md- practical end-to-end modeling flowreferences/pattern-catalog.md- reusable templates and tradeoffs
Deep source articles
Use these only when you need full explanations/examples:
- Fundamentals of type-driven code ->
references/fundamentals-of-type-driven-code.md - Type-safe validation ->
references/type-safe-validation.md - Witness pattern: type-safe access control ->
references/witness-pattern-type-safe-access-control.md - Domain modeling with types ->
references/domain-modeling-with-types.md - Making illegal states unrepresentable ->
references/making-illegal-states-unrepresentable.md