← thecodex.expert · The Codex Family of Knowledge
Swift

Generics Deep Dive

A protocol can require a type without ever naming what it actually is — associatedtype leaves that choice to each conforming type, usually inferred automatically with zero extra annotation needed.

Swift 6 associatedtype: a protocol’s own generic parameter Last verified:
Canonical Definition

associatedtype Item inside a protocol declares a placeholder type — essentially the protocol's own generic parameter — that each conforming type must fill in with something concrete, most often inferred automatically from how the type actually implements the protocol's requirements, with no explicit annotation needed. This is precisely how Swift's own Collection and Sequence protocols describe generic containers without committing to any specific element type. A where clause, attached to a generic function, extension, or protocol conformance, adds an extra constraint beyond the basic type parameter declaration — for instance, requiring two different generic collections to hold the same Element type before a function comparing them will even compile.

associatedtype: a protocol's own generic parameter

IntStack never explicitly states Item = Int anywhere — Swift infers it automatically from push's parameter type, exactly as if the compiler read the implementation and figured out what Item must mean here.

Swiftassociated_type.swift
protocol Container {
    associatedtype Item
    mutating func push(_ item: Item)
    func peek() -> Item?
}

struct IntStack: Container {
    var items: [Int] = []
    mutating func push(_ item: Int) { items.append(item) }   // Item inferred as Int
    func peek() -> Int? { items.last }
}

where clauses: constraining generic functions further

Without the where clause, comparing two DIFFERENT Container types with unrelated element types would be meaningless — the constraint requires both containers' Item types to actually match before this function will even compile.

Swiftwhere_clause.swift
func allItemsMatch<C1: Container, C2: Container>(
    _ c1: C1, _ c2: C2
) -> Bool where C1.Item == C2.Item, C1.Item: Equatable {
    return c1.peek() == c2.peek()
}

Generic extensions with constraints

This extension applies ONLY to arrays holding Equatable elements — an [Int] gets allDuplicatesRemoved(), but an array of a non-Equatable type genuinely does not, since equality comparison wouldn't be possible for it.

Swiftconstrained_extension.swift
extension Array where Element: Equatable {
    func allDuplicatesRemoved() -> [Element] {
        var result: [Element] = []
        for item in self where !result.contains(item) {
            result.append(item)
        }
        return result
    }
}

print([1, 2, 2, 3, 1].allDuplicatesRemoved())   // [1, 2, 3]

Sources

1
Apple / Swift.org. The Swift Programming Language, "Generics," docs.swift.org/swift-book.