Pattern for Mapping Result where closure throws? For mapping both failure and success?

Say I have a Result<Data, NetworkError> from a network response. Next I want to turn it into Result<Model, NetworkError>.
Or better yet: Result<Model, ModelRelatedError>

My initial approach was to use map, but that's where I realized I needed a throwing closure. Also, it only handles mapping the success or the failure (mapError, I believe?), but not both.

let networkResult: Result<Data, NetworkData>( ... ) 
let modelResult = networkResult.map { data in 
     JSONDecoder(), etc. etc. ... 
    // now I need to handle do / catch  in here...
}

I could write this out the slightly longer way, with a switch statement, do, catch, and so on. Maybe throw it in an extension. I wanted to see if there are some best practices / patterns others use here.

For now you can use flatMap and use an inner Result to capture the transform. But yes, I plan on making a formal pitch to add throwing transforms. In the meantime it’s pretty easy to add yourself.

1 Like

Ah I see. Thanks!

Is there a way to propagate a new error type? Say, after the model decoding fails, i want to end up with Result<Model, ModelError>. (the underlying networking layer in the example does not know of this decoding error, only network specific errors). So mapping Result<Data, NetworkError> to Result<Model, ModelError> .

You can call mapError to encapsulate the error in your type. Or, in your flatMap manually handle the decode using do / catch and do both in the same step.

1 Like

You want map/flatMap when the error type stays the same.
If you want to change both at the same time you might prefer using do-catch + .get().

e.g.

let networkResult = ...
do {
  let data = try networkResult.get()
  let modelResult = ... something with data ...
} catch {
  let modelError = ... something with error ...
  return .failure(modelError)
}
1 Like

Got it, thanks for the help!