0Pricing
Swift Academy · Lesson

Reusability and constraints

Design generic wrappers with type constraints (e.g., Value: Comparable ), add targeted APIs via where , and compose multiple wrappers.

Why constraints?

Write one wrapper and reuse it across many types by making it generic with constraints. Add focused APIs with where clauses and compose small wrappers.

Generic + Comparable

Use Comparable to make one Bounded work for Int, String, etc. Invalid types are rejected at compile time.

@propertyWrapper
struct Bounded<Value: Comparable> {
    private var value: Value
    private let range: ClosedRange<Value>

    var wrappedValue: Value {
        get { value }
        set {
            // clamp using Comparable
            if newValue < range.lowerBound { value = range.lowerBound }
            else if newValue > range.upperBound { value = range.upperBound }
            else { value = newValue }
        }
    }

    init(wrappedValue: Value, _ range: ClosedRange<Value>) {
        self.range = range
        self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
}

struct Stats {
    @Bounded(0...100) var score: Int = 120
    @Bounded("a"..."z") var letter: String = "Swift"
}
var st = Stats()
print(st.score)   // 100
st.letter = "m"
print(st.letter)

All lessons in this course

  1. Creating wrappers, projectedValue
  2. Reusability and constraints
  3. Common wrappers patterns (validation, caching)
← Back to Swift Academy