← ClaudeAtlas

functional-constraining-primitive-valueslisted

Use when domain values are raw strings or numbers, when the same format or range check appears in more than one place, or when ids can be swapped.
yutna/functional-design-skills · ★ 0 · AI & Automation · score 75
Install: claude install-skill yutna/functional-design-skills
# Constraining Primitive Values ## Overview A domain value is almost never "a string" or "a number". It is a booking identifier, a percentage between zero and one hundred, a quantity of at least one, an email address. When those are represented by primitives, three things follow: the constraints live in prose, any value can be passed where any other is expected, and the same check appears wherever someone remembered it. Wrapping each domain value in its own type, built only through a function that can fail, fixes all three at once. This is the cheapest structural improvement available in most codebases. ## When to use - A function signature has two or more parameters of the same primitive - The same format or range check appears in more than one place - A comment or a schema documents what values are legal - An identifier is passed as a string across module boundaries - A number is a quantity, a rate, an amount, or a duration Not for: values that genuinely are unconstrained free text with no rules. ## Core rules 1. Default. **One type per domain concept**, even when the underlying primitive is the same. `CustomerId` and `BookingId` are different types. 2. Rule. **Constructors can fail; return `Result`.** The constructor is the only place the rule lives. 3. Rule. **No public raw construction.** If the wrapper can be built directly from a primitive anywhere, the type is decoration. 4. Default. **Unwrap late, at the edge.** Inside the domain, pass the wrapper.