0Pricing
Swift Academy · Lesson

Conditional Conformance

Conform generically only when constraints are met.

Conditional Conformance is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is Conditional Conformance?

Conditional conformance makes a generic type conform to a protocol only when its type parameters satisfy certain constraints. The classic example: an Array is Equatable only if its Element is Equatable.

extension Array where Element: Equatable {
    func allEqual(to x: Element) -> Bool {
        allSatisfy { $0 == x }
    }
}

Built-In Example

The standard library already uses this: [Int] is Equatable because Int is. Two arrays compare equal element-by-element.

let a = [1, 2, 3]
let b = [1, 2, 3]
print(a == b)

Declaring Conditional Conformance

Write an extension that adds protocol conformance with a where clause. Here a wrapper conforms to Equatable only when its value type does.

struct Pair<T> {
    let first: T
    let second: T
}

extension Pair: Equatable where T: Equatable {
    static func == (l: Pair, r: Pair) -> Bool {
        l.first == r.first && l.second == r.second
    }
}

print(Pair(first: 1, second: 2) == Pair(first: 1, second: 2))

Why the Constraint Matters

Without the constraint, the compiler could not synthesize ==, because comparing the wrapped value requires the value itself to be comparable. The where clause supplies exactly that guarantee.

struct Box<T> { let value: T }
extension Box: Equatable where T: Equatable {}

print(Box(value: "hi") == Box(value: "hi"))
print(Box(value: 5) == Box(value: 9))

Conditional Codable

You can conditionally conform to Codable. A container is encodable only when its element is.

struct Wrapper<T> { let payload: T }
extension Wrapper: Codable where T: Codable {}

let w = Wrapper(payload: 42)
let data = try! JSONEncoder().encode(w)
print(String(data: data, encoding: .utf8)!)

Multiple Constraints

A where clause can list several requirements separated by commas.

struct Stack<T> { var items: [T] = [] }

extension Stack where T: Comparable {
    func maxItem() -> T? { items.max() }
}

var s = Stack<Int>()
s.items = [3, 9, 1]
print(s.maxItem()!)

Conditional CustomStringConvertible

Make a type printable only when its contents are, composing descriptions from the elements.

struct Labeled<T> { let label: String; let value: T }

extension Labeled: CustomStringConvertible where T: CustomStringConvertible {
    var description: String { label + ": " + value.description }
}

print(Labeled(label: "Age", value: 30))

Nested Conditional Conformance

Conditional conformance composes: an array of arrays of Int is Equatable because each layer chains the constraint.

let grid1 = [[1, 2], [3, 4]]
let grid2 = [[1, 2], [3, 4]]
print(grid1 == grid2)

Constraining to Another Protocol

The where clause can require the element conform to a protocol you defined, unlocking behavior built on that protocol.

protocol Priced { var price: Double { get } }
struct Item: Priced { let price: Double }

extension Array where Element: Priced {
    var totalPrice: Double { reduce(0) { $0 + $1.price } }
}

print([Item(price: 1.5), Item(price: 2.5)].totalPrice)

Same-Type Constraints

You can constrain an associated type to a specific type using ==. Here methods apply only to arrays of String.

extension Array where Element == String {
    func joinedUpper() -> String {
        map { $0.uppercased() }.joined(separator: "-")
    }
}

print(["a", "b", "c"].joinedUpper())

How the Compiler Uses It

Conditional conformance lets the compiler grant a protocol's benefits exactly when they are valid, so generic code stays both safe and maximally reusable.

struct Optional2<T> { let value: T? }
extension Optional2: Equatable where T: Equatable {
    static func == (l: Optional2, r: Optional2) -> Bool { l.value == r.value }
}
print(Optional2(value: 1) == Optional2(value: 1))

Quick Check

Test your understanding of conditional conformance.

Recap

Conditional conformance uses extension Type: Protocol where ... to grant conformance only when type parameters meet constraints. You saw it for Equatable, Codable, and CustomStringConvertible, with protocol constraints, same-type constraints (==), and nesting. It keeps generic types safe and reusable.

Frequently asked questions

Is the “Conditional Conformance” lesson free?

Yes — the full text of “Conditional Conformance” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.

What will I learn in “Conditional Conformance”?

Conform generically only when constraints are met. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Swift Academy?

No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Conditional Conformance” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Swift Academy lesson?

Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Protocols as Contracts
  2. Default Implementations in Extensions
  3. Protocol Composition
  4. Conditional Conformance
← Back to Swift Academy