When defining a protocol, it’s sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name to a type that is used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted. Associated types are specified with the associatedtype keyword. from Swift docs

Another words, Protocol with associated type is a way of declaring Generic protocol.

Problem

Protocol CustomProtocol has associated type AssociatedType. It guarantees that if an object adopts CustomProtocol argument parameter of foo function and return type of bar function are of the same type AssociatedType.

protocol CustomProtocol {
    associatedtype AssociatedType
    func foo(argument: AssociatedType)
    func bar() -> AssociatedType
}

We want to create an Array of objects that are adopting CustomProtocol

let array = [CustomProtocol]()

It won’t work. Compiler will show the following Error:

Protocol 'CustomProtocol' can only be used as a generic constraint because it has Self or associated type requirements

This erorr appears because the type of the object contained in the array is only “partially defined” until the protocol is adopted, which means all associatedtypes are defined.

Type erasure in Swift

Type erasure can be explained as the process of enforcing type constraints only at compile time and discarding the element type information at runtime.

The example of Type erasure is AnySequence. If you type AnySequence in the Playground, and then jump to its definition, you will see the following in the top left corner:

Click to see a GIF

Adding one more level of abstraction (AnySequence<Element>) fixes the problem. Operations are now forwarded to the underlying sequence, but the key difference is that Compiler now knows what the associatedtype is. In case of Sequence it is Element (Actually, there is more associated types. See my article about Sequences).

public struct AnySequence<Element> {
    // Implementation here
}

extension AnySequence : Sequence {
    /// A type that provides the sequence's iteration interface and
    /// encapsulates its iteration state.
    public typealias Iterator = AnyIterator<Element>

    /// Creates a new sequence that wraps and forwards operations to `base`.
    public init<S>(_ base: S) where Element == S.Element, S : Sequence
}

Solution

Now it’s pretty easy.

public struct AnyCustomProtocol<T>: CustomProtocol {
    func bar() -> T {
        fatalError("Needs implementation")
    }
    func foo(argument: T) {
        
    }
}

let array = [AnyCustomProtocol<Any>]() // works fine

Real world usage

For real-world usage example please, see my answer on stackoverflow.com.

Playground code

See Github gist

Further reading