I would like to use SendMessageUseCase
as a variable type, for example var sendMessageUseCase: SendMessageUseCase
but I can't.
I keep getting the error Protocol 'SendMessageUseCase' can only be used as a generic constraint because it has Self or associated type requirements
Which obviously I understand the error but it doesn't make sense.
In SendMessageUseCase
I have defined my associated type using Where
clause which means technically the compiler should be able to infer, since I have explicitly defined Input
and Output
to be SendMessageUseCaseInput
and SendMessageUseCaseOutput
respectively.
protocol UseCaseInput {}
protocol UseCaseOutput {}
protocol UseCase : AnyObject {
associatedtype Input: UseCaseInput
associatedtype Output: UseCaseOutput
func execute(input: Input, _ completion: (_ output: Output) -> ())
}
struct SendMessageUseCaseInput : UseCaseInput {
var text: String
}
struct SendMessageUseCaseOutput: UseCaseOutput {
var response: String
}
protocol SendMessageUseCase: UseCase where Input == SendMessageUseCaseInput, Output == SendMessageUseCaseOutput {
}
final class TestSendMessageUseCase : SendMessageUseCase {
func execute(input: SendMessageUseCaseInput, _ completion: () -> ()) {
}
}
// Why this doesn't work?
var sendMessageUseCase: SendMessageUseCase = TestSendMessageUseCase()
can SendMessageUseCase.Input
be anything else other than SendMessageUseCaseInput
? I don't think so which is why I think it should be inferd. But obviously I am wrong and can't understand why.
CodePudding user response:
Thanks to a comment from @Jessy I was able to come to a temporary solution.
Adding some
to the sendMessageUseCase
variable would allow us to use opaque
type but there is still a limitation as you can not have an array.
There are some talks to implement this but as of now (May, 28 2022) it still hasn't been implemented.
protocol UseCaseInput {}
protocol UseCaseOutput {}
protocol UseCase : AnyObject {
associatedtype Input: UseCaseInput
associatedtype Output: UseCaseOutput
func execute(input: Input, _ completion: (_ output: Output) -> ())
}
struct SendMessageUseCaseInput : UseCaseInput {
var text: String
}
struct SendMessageUseCaseOutput: UseCaseOutput {
var response: String
}
protocol SendMessageUseCase: UseCase where Input == SendMessageUseCaseInput, Output == SendMessageUseCaseOutput {
}
final class TestSendMessageUseCase : SendMessageUseCase {
func execute(input: SendMessageUseCaseInput, _ completion: (SendMessageUseCaseOutput) -> ()) {
}
}
var sendMessageUseCase: some SendMessageUseCase = TestSendMessageUseCase()
If anyone is interested here are the forum threads
Lifting the “Self or associated type” constraint on existentials
[ [Sema]AST][WIP] Support existentials with concrete assoc. types #21576 (PR is closed)