Casting removes all levels of Optional in Swift?

I posted this question on StackOverflow and it was suggested that it might be a good question to ask here:

We all know that you can use optional binding to unwrap an optional:

let b: String? = "bye"

if let greeting = b {
    print(greeting)  // "bye"
}

But if the value has multiple levels of optionals, only one will be removed:

let b: String?? = "bye"
if let greeting = b {
    print(greeting)  // "Optional(bye)"
}

Casting the value to the underlying type will remove the double optional:

let b: String?? = "bye"
if let greeting = b as? String {
    print(greeting)  // "bye"
}

I was surprised to find this works for any level of optionals:

let b: String??????? = "bye"
print(b as Any)  // Optional(Optional(Optional(Optional(Optional(Optional(Optional("bye")))))))

if let greeting = b as? String {
    print(greeting)  // "bye"
}

Is there an explanation of why casting removes all levels of optionals? Is this a documented behavior?

Also:

let b: String??????? = "bye"
print(b as! String)  // "bye"

but it gives the humorous warning:

Forced cast from ‘String???’ only unwraps optionals; did you mean to use ‘!!!’.

1 Like

Type casting is part of the compiler, and I assume it is trivial to you that arg as! T returns T if it succeeds. In exactly the same way it happens for String???? -> String, since it is a particular case.

The warning you get will also be raised in a simple case like the following:

let str: String? = "foo"

print(str as! String)

The compiler is trying to tell you the forced cast has the same effect as a forced unwrap – str! (or b!!!!! in your case. I haven’t counted the exclamation marks ).

Forced cast from ‘String?’ to ‘String’ only unwraps optionals, did you mean to use ‘!’?

 print(str as! String) === print(str!)