37

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 }
Tikhonov Aleksandr
  • 13,945
  • 6
  • 39
  • 53

3 Answers3

57

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

Vindur
  • 586
  • 4
  • 3
3

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.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
2

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)))

Ethan
  • 486
  • 1
  • 6
  • 15