fsharp-shared
SKILL.md
F# Shared Types and API Contracts
Philosophy: Types as Executable Specification
In F#, types aren't just data containers—they're executable specifications. Well-designed types make illegal states unrepresentable and make the code self-documenting.
Before defining types, ask:
- What concepts exist in this domain?
- What states can entities be in?
- What operations are valid for each state?
- What can go wrong? (Model errors as types, not strings)
Core Principles:
-
Make Illegal States Unrepresentable: If it can't exist in the domain, it shouldn't compile. Use discriminated unions to constrain possibilities.
-
Types Are Documentation: A well-designed type tells you what you can do with it. If you need comments to explain, the type could be clearer.
-
Separate Inputs from Entities: Create request types separate from domain entities. The API caller shouldn't set server-managed fields.