Abusing Swift’s Result Type

A tale about when the Result type shouldn’t be used.

Nikita Lazarev-Zubov
5 min readApr 21, 2023
Abusing Swift’s Result Type
Photo by Mike Kilcoyne on Unsplash

When the Result type was added to Swift’s standard library a few years ago, this simple change affected how we treat completion-based asynchronous methods enormously. Judge for yourself: Clumsy and ambiguous completion handlers like this sank into oblivion:

func getData(_ completionHandler: (_ data: Data?, _ error: Error?) -> Void)

In case someone doesn’t fully understand the ugliness of the method presented above, no, the problem is not (only) in multiple arguments of the closure. The main issue is the arguments’ nullability: Every time, you have to check both of them in order to determine whether the call succeeded or failed. What if both of them are nil? Or even worse, both are not nil?

Result solves the problem rather elegantly:

func getData(_ completionHandler: (_ result: Result<Data, Error>) -> Void)

So, instead of this mess:

getData { data, error in
if let error {
// Handle the error.
}
if let data {
// Use the data.
}
// Handle the probably impossible case of both error and data being nil.
}

We have this one:

getData { result in
switch result {
case…

--

--

Nikita Lazarev-Zubov

Swift and general programming topics, Agile software development, soft skills