I’m trying to determine if a given type t
(Any.Type
) is an optional type, I’m using this test
t is Optional.Type
A bit late for the party. But, I ran into the same problem. Here is my code.
func isOptional(_ instance: Any) -> Bool {
let mirror = Mirror(reflecting: instance)
let style = mirror.displayStyle
return style == .optional
}
let a: Int = 1 // false
let b: Int? = 2 // true
let c: Double = 3.0 // false
let d: Double? = 4.0 // true
let e: NSString = "Hello" // false
let f: NSString? = "Hello" // true
isOptional(a) // fasle
isOptional(b) // true - warning
isOptional(c) // false
isOptional(d) // true - warning
isOptional(e) // false
isOptional(f) // true - warning
It looks good to me. swift4
You can do something like this:
extension Mirror {
static func isOptional(any: Any) -> Bool {
guard let style = Mirror(reflecting: any).displayStyle,
style == .optional else { return false }
return true
}
}
Usage:
XCTAssertTrue(Mirror.isOptional(any: Optional(1)))
Or if you need to cast from Any to Optional
protocol _Optional {
var isNil: Bool { get }
}
extension Optional: _Optional {
var isNil: Bool { return self == nil }
}
func isNil (_ input: Any) -> Bool {
return (input as? _Optional)?.isNil ?? false
}
Usage:
isNil(nil as String?) // true
isNil("") // false
You could use generics to achieve this:
func isOptional<T>(x:T?)->Bool
{
return true
}
func isOptional<T>(x:T)->Bool
{
return false
}
Edit
The code above can be used to know if a variable is of optional type. The only way i've figured out to know about a variable containing a type is by using reflection:
var t1:Any.Type=(String?).self
var t2:Any.Type=(String).self
Mirror(reflecting: t1).description
Mirror(reflecting: t2).description
The first call to Mirror gives the string "Mirror for Optional<String>.Type"
, and the second gives "Mirror for String.Type"
.
I understand that comparing string is not a convenient way to do this check, i will try again to find something more performant..
Assuming that what you are trying to do is something like this:
let anyType: Any.Type = Optional<String>.self
anyType is Optional<Any>.Type // false
Sadly swift currently (as of Swift 2) does not support covariance nor contravariance and type checks directly against Optional.Type
cannot be done:
// Argument for generic parameter 'Wrapped' could not be inferred
anyType is Optional.Type // Causes error
An alternative is to make Optional
extend an specific protocol, and check for that type:
protocol OptionalProtocol {}
extension Optional : OptionalProtocol {}
let anyType: Any.Type = Optional<String>.self
anyType is OptionalProtocol.Type // true