Home > Software engineering >  How do I fix this generic constraint error?
How do I fix this generic constraint error?

Time:11-03

How do you initialize a ViewModel with different use-cases? My requirements are to test my ViewModel with a MockUseCase and an APIUseCase (actual behavior), but I'm getting some errors. I tried different approaches, but nothing worked. Here is the error that I'm getting now:

enter image description here

protocol BaseUseCase {
    associatedtype _Request
    associatedtype _Response
    func execute(_ command: _Request, response: @escaping (_Response) -> Void)
}

   

APIUseCase:

struct APIUseCase : BaseUseCase {
   enum Request {
       case getPosts
   }
   enum Response {
       case recievedPosts(_ posts: [String])
   }
    
   typealias _Request = Request
   typealias _Response = Response
   
   func execute(_ command: _Request, response: @escaping (_Response) -> Void) {
       switch command {
           case .getPosts:
               response(.recievedPosts(["Post Returning from API"]))
       }
   }
}

MockUseCase:

struct MockUseCase : BaseUseCase {
    enum Request {
        case getPosts
    }
    enum Response {
        case recievedPosts(_ posts: [String])
    }
    typealias _Request = Request
    typealias _Response = Response
    
    func execute(_ command: _Request, response: @escaping (_Response) -> Void) {
        switch command {
            case .getPosts:
               response(.recievedPosts(["Post Returning from Mock"]))
        }
    }
}

ViewModel:

class ViewModel {
    var usecase: any BaseUseCase
            
    init(usecase: some BaseUseCase  = APIUseCase()) {
         self.usecase =  usecase
    }
        
    func execute() {
         usecase.execute(.getPosts) { response in }
    }
}

CodePudding user response:

You can't inject a protocol with associated types, unless you make your class with a generic type:

i.e: ViewModel<T: BaseUseCase> {}

Is there any reason you're defining Request and Response in this way ? Since, they are the same, I don't see any reason in doing so.

enum Request {
    case getPosts
}
enum Response {
    case recievedPosts(_ posts: [String])
}

protocol BaseUseCase {
    func execute(_ command: Request, response: @escaping (Response) -> Void)
}

struct APIUseCase : BaseUseCase {

   func execute(_ command: Request, response: @escaping (Response) -> Void) {
       switch command {
           case .getPosts:
               response(.recievedPosts(["Post Returning from API"]))
       }
   }
}

struct MockUseCase : BaseUseCase {

    func execute(_ command: Request, response: @escaping (Response) -> Void) {
        switch command {
        case .getPosts:
            response(.recievedPosts(["Post Returning from Mock"]))
        }
    }
}

class ViewModel {
    var usecase: BaseUseCase

    init(usecase: BaseUseCase) {
        self.usecase =  usecase
    }

    func execute() {
        usecase.execute(.getPosts) { response in }
    }
}
  • Related