Determine If Any.Type Is Optional

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.

What is the type of a Java empty Optional?

The Optional class is a container that might contain a specific element. As such, it has two concepts:

  • The type it might contain
  • The actual object it contains

The type it might contain is specified trough generics. Generics only exist at compile time and are lost at runtime.

To answer your questions:

  1. When using an Optional, you usually define it to possibly contain a type, like this:
Optional<String> optionalString;

At this point we know that optionalString might contain a String. If we do this:

Optional<String> optionalString = Optional.empty();

It doesn't actually contain anything, but we can use it anywhere an Optional<String> is required.


  1. The type of the Optional is inferred trough its usage. Like above, you specify the Optional.empty() to be an Optional<String>. You can also specify its type trough the return value of a method, like so:
public Optional<Integer> findNumber() {
return Optional.empty();
}

  1. Since the type is no longer present at runtime, there is no way to check what the optional contains at this point. At runtime, an empty Optional has no type.

typescript exclude optional fields from type (deep)

With this recursive type:

type OnlyRequired<T> =
T extends object
? { [K in keyof T as {} extends Pick<T, K> ? never : K]: OnlyRequired<T[K]> }
: T;

If T is a primitive, we don't need to do anything. However if it is an object we have to go through each key and get only the ones that can't be optional (credit to @jcalz) and then recursively gets only required keys of T[K].

Note that functions need a little special handling and checking for undefined is not exhaustive or the best way to check for optional properties but it does work for your example.

Playground



Related Topics



Leave a reply



Submit