Extension optional Array with Optional Element. Is it even possible?

I have a protocol FooProtocol . and a class Bar<Foo:FooProtocol> . Inside a class an Array var mess: [Foo?]? to keep [foo1, foo2, nil, foo3...] or nil And I try to make extension for this array to count new Foo object. I prefer to have protocols, because Foos could be very different objects delivered from outer world.

protocol FooProtocol {
  ....
  init(from heaven: Int)
}

extension Optional where
  Wrapped: Collection,
  Wrapped.Element == Optional,
  Wrapped.Element.Wrapped: FooProtocol // 'Wrapped' is not a member type of 'Wrapped.Element'
{
  var united: Wrapped.Element.Wrapped { // Nope
    let i = ...
    return Wrapped.Element.Wrapped(from: i) // Nope
    
  }
}

class Bar<Foo:FooProtocol> {
  var mess: [Foo?]?
  init (with mess: [Foo?]?) {
    self.mess = mess
  }
  var important: Foo {
    return mess.united
  }
}

I tried
Wrapped.Element == Optional
Wrapped.Element : Optional

Errors. Is it my fault or compiler?

The feature you're looking for is "parameterized extensions" and is not yet available in the language. You can find more information and current workarounds here.

I have many use cases for generic code, where I want to conditionally add functionality through extensions whenever one of the generic types are optional.

In order to make that work currently, you have to define a protocol and make Optional conform to it.

Eg:

protocol OptionalType {
  associatedtype Wrapped
  var optional: Wrapped? { get }
}

extension Optional: OptionalType {
  var optional: Self { self }
}

extension Array where Element: OptionalType, Element.Wrapped: Foo {
  // ...
}

Since, in your extension, Element won’t be known to be an Optional (since more types could conform to the OptionalType protocol), you’d need to call the protocol requirement element.optional to turn the protocol type into a proper optional type.

1 Like