Use the mapError operator in Combine to transform errors from one type to another.

import Combine

enum CustomError: Error {
    case failed
}

struct ErrorWrapper: Error {
    let error: Error

    init(_ error: Error) {
        self.error = error
    }
}

let numbers = [2, 4, 6, 8, 9, 11]

func even(_ number: Int) throws -> Int {
    guard number % 2 == 0 else {
        throw CustomError.failed
    }
    return number
}

numbers.publisher
    .tryMap(even)
    .mapError { ErrorWrapper($0) }
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("Finished")
        case .failure(let error):
            print("Error: \(error)")
        }
    }, receiveValue: { value in
        print("Value: \(value)")
    })

In the above code:

  1. The numbers array contains some numbers.
  2. The even function throws an error if the number is not even.
  3. The tryMap operator transforms the emitted value using the even function.
  4. The mapError operator transforms the error from CustomError to ErrorWrapper.
  5. The sink subscriber prints the received values and errors.

When you run the code, you will see the following output:

Value: 2
Value: 4
Value: 6
Value: 8
Error: ErrorWrapper(error: CustomError.failed)

If the signature of a function or a closure matches the signature of the closure passed to the mapError operator, you can pass the function or closure directly to the operator.

//...
    .mapError(ErrorWrapper.init)
//...