Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Just with flatMap produce Failure mismatch. Combine

Tags:

swift

combine

I have such code

func request(request: URLRequest) -> AnyPublisher<Data, Error> {
    return Just(request)
        .flatMap { request in
            RequestManager.request(request) // returns AnyPublisher<Data, Error>
    }
    .eraseToAnyPublisher()
}

and I'm getting compile error:

Instance method flatMap(maxPublishers:_:) requires the types Just.Failure (aka Never) and Error be equivalent

And it's clear, because Just has Never as Failure and .flatMap requires Error as Failure, so Never != Error

I see 2 approaches:

  • using right Publisher, instead of Just, but I didn't find good candidate for this.

  • using some operator like .mapError, .mapError { $0 as Error }, but I'm not sure that it's great idea.

Any ideas how to handle it?

UPDATE:

it makes more sense to use

.setFailureType(to: Error.self)

or

.mapError { $0 as Error }
like image 661
Tikhonov Aleksandr Avatar asked Aug 18 '19 10:08

Tikhonov Aleksandr


3 Answers

There is special operator setFailureType(to:). You can override failure type to whatever error type you need.

func request(request: URLRequest) -> AnyPublisher<Data, Error> {
    return Just(request)
        .setFailureType(to: Error.self)
        .flatMap { request in
            RequestManager.request(request) // returns AnyPublisher<Data, Error>
    }
    .eraseToAnyPublisher()
}

https://developer.apple.com/documentation/combine/just/3343941-setfailuretype

like image 121
Vindur Avatar answered Nov 18 '22 22:11

Vindur


If you call .mapError() on the Just output, it will change the type to include Error, but that closure will never be called (so I wouldn’t worry) — this is what I would do unless someone has a better idea.

Normally, the Self.Error == P.Error on flatMap makes sense, as you can’t just ignore errors coming from Self. But, when Self.Error is Never, you can ignore them and produce your own errors.

like image 20
Lou Franco Avatar answered Nov 18 '22 22:11

Lou Franco


While the accepted answer certainly works it's pretty verbose. I stumbled on an alternative syntax using Result<Success,Failure).publisher that is somewhat more succinct:

Result.Publisher(.success(request))

(Note that in this case I'm depending on Swift to be able to infer the error type, but you might need to declare it explicitly: Result<URLRequest, Error>.Publisher(.success(request)))

like image 2
Ethan Avatar answered Nov 18 '22 22:11

Ethan