Typealias conformance to protocols, why can't this simple thing be implemented?

It's something like that, but not that. If you don't specify, the class constraint is assumed. (UIView in this case.)

class MyViewDelegate: MyDelegate<UIView> {
  override func getView() -> UIView { .init() }
}

class MyTableViewDelegate: MyDelegate<UITableView> {
  override func getView() -> UITableView { .init() }
}

getViewIfPossible(delegate: MyViewDelegate()) // UIView?.some
getViewIfPossible(delegate: MyTableViewDelegate()) // UIView?.none

So, just switch to a protocol:

protocol Delegate<View>: MyDelegateProtocol {
  associatedtype View: UIView
  func getView() -> View
}

extension MyDelegate: Delegate { }

func getViewIfPossible(delegate: some MyDelegateProtocol) -> (some UIView)? {
  (delegate as? any Delegate)?.getView()
}

getViewIfPossible(delegate: MyViewDelegate()) // UIView?.some
getViewIfPossible(delegate: MyTableViewDelegate()) // UIView?.some

The protocol should be superfluous, but it's not. any MyDelegate should work, and would be a step towards what this thread is about. Until that kind of thing gets through Swift Evolution, we'll need protocols that only apply to one type, as a workaround. Simplified:

protocol P<T> { associatedtype T }
final class C<T>: P { }
struct S<T>: P { }

func ƒ<T>() -> some P<T> { S() } // compiles
func ƒ<T>() -> some C<T> { C() } // compiles except for the bug that says it's a redeclaration (https://github.com/apple/swift/issues/53122)
func ƒ<T>() -> some S<T> { S() } // An 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class

Somebody made a thread about that recently but I can't find it.

1 Like