How to Check If a Type Is Optional in Swift

Determine if Any.Type is Optional

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

How can you check if a type is Optional in Swift?

This is a hacky but working solution:

func isOptional(_ type: Any.Type) -> Bool {
let typeName = String(describing: type)
return typeName.hasPrefix("Optional<")
}

Test:

let t1 = Int?.self
let t2 = Bool.self

print(isOptional(t1))
// true

print(isOptional(t2))
// false

Given a Swift `Any` type can I determine if it's an `Optional`?

You can use runtime introspection using Mirror:

let foo: String? = "foo"
let bar: String = "bar"
var a: Any = foo

// if wrapping an optional, the reflection of the value has
// a displaystyle "optional"
if let displayStyle = Mirror.init(reflecting: a).displayStyle {
print(displayStyle) // optional
}

// for a non-optional fundamental native type: no displaystyle
a = bar
if let displayStyle = Mirror.init(reflecting: a).displayStyle {
print(displayStyle)
} // prints nothing

Optional/non-optional example where the underlying type is user-defined (non native):

struct Foo {}
let foo: Foo? = Foo()
let bar: Foo = Foo()
var a: Any = foo

// if wrapping an optional, the reflection of the value has
// a displaystyle "optional"
if let displayStyle = Mirror(reflecting: a).displayStyle {
print(displayStyle) // optional
}

// for a non-optional non-fundamental type:
a = bar
if let displayStyle = Mirror(reflecting: a).displayStyle {
print(displayStyle) // struct
}

If you don't want need to use the binded displayStyle variable (e.g. for printing) but simply want check whether the wrapped value is any kind of optional, you can add a boolean clause to the if statement that holds the optional binding of the displayStyle case,

if let displayStyle = Mirror(reflecting: a).displayStyle,
displayStyle == .optional {
// is an optional ...
}

... or remove the binding entirely in favour of a single conditional expression using the nil coalescing operator (??)

if Mirror(reflecting: a).displayStyle ?? .class == .optional {
// is an optional
}

Note however that for all the methods above, this simply tells you as dev whether the type wrapped by the Any instance is optional or not: Swifts typing system still knows nothing of the sort.

swift type(of:) - show nonoptional type of optional

You can unwrap the Optional with the ! operator:

 print(String(describing: type(of: check!)))

Swift / how to check for existence of optional value

The crash is because of forced unwrap in the line

if likes?.valueForKey(user) as! String == user {

Try this way:

if let userExist = likes?.valueForKey(user) as? String where userExist == user {

//Do your work.
}

You have to use this optional binding or guard keyword.

Check if string contains optional string in Swift, but only if it's not nil

There is a map on Optional that executes the provided closure only if the optional is not nil. You can use map along with the nil coalescing operator ?? to provide the default value of true if the map returns nil because the filter is nil:

func process(items: [String], filter: String?) {
for item in items {
if filter.map(item.contains) ?? true {
// process item
}
}
}

False positive on optional in Swift5.4

Your example code prints "bar exists" in Xcode 12.4 also.

Anyway, try this implementation of require instead:

func require<T>(_ name: String) throws -> T {
guard let index = self.index(forKey: name) else {
throw DictionaryExtractionError.missingProperty(name)
}
guard let t = self[index].value as? T else {
throw DictionaryExtractionError.casting(name)
}
return t
}


Related Topics



Leave a reply



Submit