Search code examples
swiftprotocolsextension-methods

Use a protocol rather than a struct as an (optional array) extension?


Say you have

struct Screw: Codable {
  let id: String
  ..  more
}
struct Nail: Codable {
  let id: String
  ..  more
}

then

struct Parts: Codable {
  var Screws: [Screw]?
  var Nails: [Nail]?
}

and an extension on the optional array

extension Optional {
    mutating func blah() where Wrapped == [Screw] {
        if self == nil { self = [] }
        // we use the .id property ..
        if self!.count > 13 && self![13].id == 666 { self?.remove(at: 13) }
    }
}

you can then conveniently

stuff.parts.Screws.blah()

However if I sensibly

protocol IDable {
    var id: Int { get }
}
struct Screw: Codable, IDable { ..
struct Nail: Codable, IDable { ..

It seems you can NOT do this,

extension Optional {
    mutating func blah() where Wrapped == [IDable] { ..

Because at compile time

stuff.parts.Screws.blah()

Instance method 'blah()' requires the types '[Screw]' and '[any IDable]' be equivalent

Is there a way to achieve this?


Solution

  • Encapsulating the solution from the linked question, to this actual situation, the solution is ...

    mutating func blah() where Wrapped == [Screw] {
    

    becomes

    mutating func blah<T: IDable>() where Wrapped == [T] {
    

    or

    mutating func bleh(item: Screw) where Wrapped == [Screw] {
    

    becomes

    mutating func bleh<T: IDable >(item: T) where Wrapped == [T] {