How to get the unwrapped type from an optional type in Swift?

Assuming you have an optional

let someVar: String?

then print(type(of: someVar)) will print

Optional<String>

but if you add the following extension to Optional

protocol OptionalProtocol {
 func wrappedType() -> Any.Type
}

extension Optional: OptionalProtocol {
 func wrappedType() -> Any.Type {
   return Wrapped.self
 }
}

then print(someVar.wrappedType()) will print

String

No reflection whatsoever


Summary

As long as the optional is not referenced by Any or AnyObject the code will work fine.

For Any you will have to cast it to OptionalProtocol first. Running

let someVar: String?
let anyVar = someVar as Any

if let op = anyVar as? OptionalProtocol {
    print(op.wrappedType())
}

will print

String


As for AnyObject, strangely enough (at least for me), it doesn't cast to OptionalProtocol.


The original StackOverflow answer can be found here


I played with your idea a little bit, but I think there isn't a real way to do that, since you can't get the type of the associated value of an enumeration, yet. Hence Optionals are basically Enumerations, we have a problem here.

My idea would be to test for all possible value types in your model objects could be or hold. Like:

let myModelObject:Any? = someWayToGetTheData()
if let aString = myModelObject as? String {
    // do everything you need to store a string
} 
else if let anInteger = myModelObject as? Int {
    // do everything you need to store an integer
} 

// and so on ...

Since your json and your model must have a predefined number of supported conversions that is a possible way, and as far as I understand your original problem, it's basically as useful as testing for the dynamic associated value type of an Optional Enumeration, which will lead into a chain of if-else statements as well.

Tags:

Swift

Swift2