0Pricing
Swift Academy · Lesson

Constraining Associated Types

Limit associated types in generic contexts.

Constraining Associated Types is a free Swift Academy lesson on CoddyKit — lesson 3 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.

Associated Types Recap

A protocol can declare an associated type with associatedtype, a placeholder a conforming type fills in. Element in a container protocol is the classic example.

protocol Container {
    associatedtype Item
    var count: Int { get }
    func item(at i: Int) -> Item
}

Conforming with a Concrete Type

A conforming type fixes the associated type, often inferred from how it is used.

protocol Container {
    associatedtype Item
    func item(at i: Int) -> Item
}
struct IntBox: Container {
    let values: [Int]
    func item(at i: Int) -> Int { values[i] }
}
print(IntBox(values: [10, 20]).item(at: 1))

Constraining the Associated Type

Add a constraint right in the declaration: associatedtype Item: Comparable forces every conformer's item type to support comparison.

protocol Sorted {
    associatedtype Item: Comparable
    var items: [Item] { get }
}
struct Nums: Sorted { let items: [Int] }
print(Nums(items: [3, 1, 2]).items.sorted())

Using the Constraint

Because the associated type is constrained, protocol extensions can rely on that capability.

protocol Sorted {
    associatedtype Item: Comparable
    var items: [Item] { get }
}
extension Sorted {
    var smallest: Item? { items.min() }
}
struct Nums: Sorted { let items: [Int] }
print(Nums(items: [5, 2, 8]).smallest!)

where on associatedtype

Swift also allows a where clause on an associated type to relate it to another associated type or a nested type.

protocol Sequence2 {
    associatedtype Element
    associatedtype Iterator: IteratorProtocol where Iterator.Element == Element
}

Constraining to Another Protocol

An associated type can be required to conform to a protocol you define, layering behavior.

protocol HasName { var name: String { get } }
protocol Registry {
    associatedtype Entry: HasName
    var entries: [Entry] { get }
}
struct User: HasName { let name: String }
struct Users: Registry { let entries: [User] }
print(Users(entries: [User(name: "Ada")]).entries[0].name)

Multiple Associated Types

A protocol may declare several associated types, each independently constrained.

protocol Mapping {
    associatedtype Key: Hashable
    associatedtype Value
    func value(for k: Key) -> Value?
}
struct Phonebook: Mapping {
    let data: [String: Int]
    func value(for k: String) -> Int? { data[k] }
}
print(Phonebook(data: ["x": 1]).value(for: "x")!)

Default Associated Type

You can give an associated type a default with =, used when a conformer does not otherwise specify it.

protocol Producer {
    associatedtype Output = String
    func make() -> Output
}
struct Hello: Producer {
    func make() -> String { "hi" }
}
print(Hello().make())

Constraints Enable Generic Algorithms

With a constrained associated type, a protocol extension can implement real algorithms shared by all conformers.

protocol Scored {
    associatedtype Score: Comparable
    var scores: [Score] { get }
}
extension Scored {
    var best: Score? { scores.max() }
}
struct Game: Scored { let scores: [Int] }
print(Game(scores: [10, 40, 25]).best!)

Same-Type Constraints in Extensions

Outside the protocol, you can constrain the associated type further when extending the protocol.

protocol Box2 {
    associatedtype Content
    var content: Content { get }
}
extension Box2 where Content == Int {
    var doubled: Int { content * 2 }
}
struct IB: Box2 { let content: Int }
print(IB(content: 7).doubled)

Why Constrain?

Constraining associated types is how protocols stay generic yet powerful: the constraint is a promise the extension and callers can rely on.

protocol Listy {
    associatedtype E: Equatable
    var elements: [E] { get }
}
extension Listy {
    func has(_ x: E) -> Bool { elements.contains(x) }
}
struct L: Listy { let elements: [String] }
print(L(elements: ["a", "b"]).has("b"))

Quick Check

Test your understanding of constraining associated types.

Recap

You can constrain associated types directly (associatedtype Item: Comparable), relate them with where clauses, require protocol conformance, give defaults with =, declare multiple associated types, and refine them in extensions. Constraints let protocol extensions implement shared, type-safe algorithms.

Frequently asked questions

Is the “Constraining Associated Types” lesson free?

Yes — the full text of “Constraining Associated Types” 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 “Constraining Associated Types”?

Limit associated types in generic contexts. 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 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Constraining Associated Types” 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. Type Parameter Constraints
  2. where Clauses on Functions
  3. Constraining Associated Types
  4. Generic Subscripts and Extensions
← Back to Swift Academy