Extensions on Optional Types

Eric Downey
Swift2Go
Published in
3 min readAug 26, 2018

Hey everyone! I wanted to write this quick article because I love using this technique and it’s not the most obvious implementation. So, if you’ve worked in Swift for more than 2 minutes, then you’ve probably seen Optionals. There are great articles explaining what these things are and how to work with them. I am not going to get into that here. What I want to talk about is the dreaded

Expression implicitly coerced from ‘String?’ to ‘Any’

error that you get every time you try to print an Optional. Okay, so it’s not the most important use case in the world, but without it, your code would either be littered with warnings, or you would have to cast everything to an Any type every time you did this. So the following implementation:

let val: String? = nil
//…
print(val) // Warning is generated here

would become

let val: String? = nil
//…
print(val as Any)

and if you have lots of these or if the type of val changes, this can become a nightmare to maintain. So, what is the elegant fix because it definitely is not using String(describing: val), which is the suggested fix in Xcode. I’m so glad you asked 😁. To fix this, let’s write an extension on the Optional type and yes that is completely possible and really cool! Let’s start by writing the following:

extension Optional where Wrapped == String {}

In the previous code block, we are extending the Optional type where the Wrapped type is a String. The Wrapped property is the identifier for the generic type that is declared with the Optional declaration (Swift Generics). That means whatever code we write in this extension will only be available to optional string types (String?). So let’s implement our extension. In the next code block we are going to add a new property called valueOrEmpty. Here is the code:

extension Optional where Wrapped == String {
var valueOrEmpty: String {
guard let unwrapped = self else {
return “”
}
return unwrapped
}
}

First, we unwrap the optional in a guard, same as any other optional. Then if the value exists, we return it, otherwise, we return an empty string. Now, how does this affect the code from earlier? Instead of casting to an Any type, we would now have the following:

let val: String? = nil
//…
print(val.valueOrEmpty)

This allows us to turn an optional string into a non-optional string where the string will either have a value or it will be empty. As you can tell, this can be applied to lots of things other than just strings and printing out values.

I’ve gotten tripped up multiple times when I want to compare two booleans values where one or both are optional Bools. We can create an extension that gives us false if the value is nil. This is most likely a safe assumption because if the value of a bool is nil, we want the failure case of an if or guard statement to execute. And that brings me to my final point.

With Great Power, Comes Great Responsibility

This can be used for all kinds of things, you could go nuts with it. But remember, optionals are actually a really great thing in our code. When I’ve worked with other languages and I unexpectedly get a null pointer exception, I want to tear my hair out because there are no optionals (looking at you Java, you know what you did). This should not be used to get around all optionals. There are plenty of cases where optionals are necessary and good.

Alright, now that my PSA is over, hopefully this quick article revealed some cool extensions you can write in your code. Thank you for reading! 😁

Github

Versions

  • Xcode 10 beta 6 — Playground
  • Swift 4.2

References

--

--

Eric Downey
Swift2Go

Comics and Code! I'm a software consultant with a passion for iOS & Swift