Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding Type Erasure when implementing the Repository Pattern

I'm trying to implement the repository pattern in Swift in a generic way. The problem that I'm currently facing is, that it seems like I have to write type erasure wrappers for all my repositories. Am I missing something here? Is there a better way to do this or to make the compiler happy at this point?

// 1
class Item {}

// 2
protocol Repository {
    associatedtype T
}

// 3
protocol AnyItemRepository: Repository where T == Item {}

// 4
class ItemRepository: AnyItemRepository {
    static let shared = ItemRepository()

    private init() {}
}

// 5
class ViewController {

    // 6
    var itemRepository: AnyItemRepository? = ItemRepository.shared

}
  1. One of many entities
  2. The base repository interface that can be extended if necessary or implemented directly
  3. A special item repository interface that guarantees additional functionality on top of the base repository
  4. Concrete repository implementation for a specific entity type
  5. Some class that needs to access the data
  6. Dependency to any item repository. The compiler errors on this line: Protocol 'AnyItemRepository' can only be used as a generic constraint because it has Self or associated type requirements
like image 848
Martin Avatar asked Dec 09 '25 22:12

Martin


1 Answers

You don't need the AnyItemRepository type. Just write extension methods on Repository like so:

public extension Repository where T == Item {
   func doSomethingSpecial(with items: [Item]) {
      // blah blah
   }
}

In your view controller, you can't use Repository or AnyItemRepository in this way because these are generic type constraints. You must either use a concrete type or generically parameterize ViewController.

class RepositoryViewController<R>: UIViewController where R: Repository, R.T == Item {
    var itemRepository: R { get }
}

class ViewController: RepositoryViewController<ItemRepository> {
   override var itemRepository: ItemRepository {
      return ItemRepository.shared
   }
}

(The above is untested pseudocode designed to give you the gist. It has never been run by anyone ever and may not even compile.)

like image 85
Gregory Higley Avatar answered Dec 13 '25 12:12

Gregory Higley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!