I have two functions which return AnyPublisher with different failure type: Never and Error. When using these functions in the CombineLates, then compilation fails with an error: Generic struct 'CombineLatest' requires the types 'Error' and 'Never' be equivalent
func foo() -> AnyPublisher<Int, Never> {
Result<Int, Never>
.success(1).publisher
.eraseToAnyPublisher()
}
func boo() -> AnyPublisher<Int, Error> {
Result<Int, Error>
.failure(NSError(domain: "d", code: -1))
.publisher.eraseToAnyPublisher()
}
Publishers.CombineLatest(foo(), boo())
Generic struct 'CombineLatest' requires the types 'Error' and 'Never' be equivalent
How to use CombineLates when publisher's failure types are not equivalent?
Whenever you need to match failure types in Combine, for a Never
failure type, like a Just
publisher, you'd use setFailureType(to:)
:
let p: AnyPublisher<Int, Never> = ...
let p1 = p.setFailureType(to: Error.self)
.eraseToAnyPublisher() // AnyPublisher<Int, Error>
For a non-Never
failure, you'd need to use .mapError
:
let p2 = p1.mapError { CustomError(wrapping: $0) }
.eraseToAnyPublisher() // AnyPublisher<Int, CustomError>
So, in your case, if you want to change foo
's return value, you'd do:
func foo() -> AnyPublisher<Int, Error> {
Result<Int, Never>
.success(1).publisher
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
And if you don't want to change foo
, but still use with with bar
, you can do:
Publishers.CombineLatest(foo().setFailureType(to: Error.self), boo())
.map { (f, b) in
// f and b are Ints, as emitted by foo and bar, respectively
}