Reputation: 11390
I'm switching over a project from a custom Result type to the native Swift Result type and keep running into this - or similar - error messages:
Member 'success' in 'Result<_, Error>' produces result of type 'Result<Success, Failure>', but context expects 'Result<_, Error>'
protocol DataFetcher {
func request<T>(completion: @escaping (Result<T, Error>) -> Void )
}
struct RandomFetcher: DataFetcher {
func request<String>(completion: @escaping (Result<String, Error>) -> Void) {
let str = "Hello"
completion(.success(str))
}
}
The idea is to have make a bunch of generic Fetchers for different data extraction calls and to pass these to VC's who would have a var fetcher: DataFetcher
property. The VC's know which concrete types they expect from their request. I can't use an associated type
as I need to save a bunch of these in an array and I thought I could get away with just the generic implementation - but it almost seems as if the Result type being declared as a generic in the protocol, means that it won't accept when I specify it in the implementation. What am I missing?
Upvotes: 1
Views: 875
Reputation: 285064
In this case an associated type is preferable
protocol DataFetcher {
associatedtype FetchType
func request(completion: @escaping (Result<FetchType, Error>) -> Void )
}
struct RandomFetcher: DataFetcher {
func request(completion: @escaping (Result<String, Error>) -> Void) {
let str = "Hello"
completion(.success(str))
}
}
Upvotes: 1
Reputation: 299355
func request<String>(completion: @escaping (Result<String, Error>) -> Void) {
This is a classic generics mistake in Swift. This does not mean "request requires T==String
." This means "there is an arbitrary type called String
that this function accepts." There is no relationship between this String
and Swift.String
.
What you're trying to do here violates the protocol. The protocol says that the caller gets to pick any T they want. You can't conform to that protocol with a restricted T.
If you want the conforming type (RandomFetcher) to get to decide the type of T, then you have to use an associatedType (that's what associatedType means).
The thing you're trying to build is pretty common, but not trivial, and requires a different way of thinking about the problem. I walk through it step-by-step in this series.
Upvotes: 4