Type-Erasing in Swift | AnyView behind the scenes

If you have protocol that looks like this

protocol MyProtocol {
    associatedtype A
    func requirement() -> A
}

then there are two ways you can type-erase it that I know

the easier one:

struct TypeErased {
    typealias A = Any
    init<T: MyProtocol>(_ value: T) {
        self._requirement = value.requirement
    }

    private let _requirement: () -> Any
    func requirement() -> Any {
        return self._requirement()
    }
}

and the more complicated, but I think this one is used by standard library (sorry for meaningless names)

private protocol TypeErasedBox {
    var base: Any { get }
    func requirement() -> Any
}
private struct ConcreteTypeErased<Base: MyProtocol>: TypeErasedBox {
    let baseProto: Base
    var base: Any {
        return self.baseProto
    }
    func requirement() -> Any {
        return self.baseProto.requirement()
    }
}

struct TypeErased: MyProtocol {
    typealias A = Any
    private let box: TypeErasedBox
    init<T: MyProtocol>(_ value: T) {
        self.box = ConcreteTypeErased(baseProto: value)
    }
    var base: Any {
        self.box.base
    }
    func requirement() -> Any {
        return self.box.requirement()
    }
}
8 Likes