Jon_Shier
(Jon Shier)
1
I'm attempting to create protocols to abstract Alamfire's request -> response pipeline to create a generic relationship between the two. Abstractly, the types look like this:
struct DataResponse<Success, Failure: Error> {}
final class DataRequest {}
enum AFError: Error {}
protocol PublishableRequest {
associatedtype Response: PublishedResponse
}
protocol PublishedResponse {
associatedtype Success
associatedtype Failure: Error
}
extension DataResponse: PublishedResponse {}
extension DataRequest: PublishableRequest {
typealias Response = DataResponse
}
Despite the fact that DataResponse conforms to PublishedResponse, type alias Response = DataResponse isn't enough to conform to the protocol, the compiler continuously complains that there's no inner type Response. Is there a way to express the typealias to conform to the protocol?
royhsu
(Roy Hsu)
2
You can make DataRequest generic first. Then do the conformance.
struct DataResponse<Success, Failure: Error> {}
final class DataRequest<Success, Failure: Error> {
typealias Response = DataResponse<Success, Failure>
}
enum AFError: Error {}
protocol PublishableRequest {
associatedtype Response: PublishedResponse
}
protocol PublishedResponse {
associatedtype Success
associatedtype Failure: Error
}
extension DataResponse: PublishedResponse {}
extension DataRequest: PublishableRequest {}
Jon_Shier
(Jon Shier)
3
Thanks. Your solution works but making DataRequest generic isn't possible. It's part of Alamofire's public API, and since requests can have multiple responses depending on parsing, it's not a requirement we'd want anyway. I do find it odd that the compiler accepts the definition of the typealias in my example, but can't use it to fulfill the protocol requirement.
lukasa
(Cory Benfield)
4
Isn't Swift totally right here?
DataResponse is not a type, it's a family of types. For example, DataResponse<Int, NIO.IOError> is one possible DataResponse. DataResponse<CGFloat, Network.NWError> is another.
This means that when your DataRequest extension says that Response = DataResponse, Swift doesn't know which DataResponse you mean. There is type information missing here.
I think this is probably a compiler error checking bug. The actual issue is that you haven't specified a type that actually exists for the typealias, but Swift hasn't noticed this.
That's fine, you should just say what the DataResponse types are for DataRequest.
1 Like
Jon_Shier
(Jon Shier)
5
You're right, there's no way to define the actual type with DataRequest. I could use the protocol to define one specific type, but I think I'm going to explore the problem space more before trying to come up with a single abstraction. This is all for my Combine work on Alamofire, so perhaps the publisher could provide the types necessary here, but I can start by making them concrete.