May I present this non-recursive solution which doesn't erase the type (but still works for Any?
):
func funwrap<T>(_ v: T????????????????????) -> T? {
return (v as? T?) ?? nil
}
It works for 0 through 20 levels of optionality.
Adding more than 20 gets hard on the type checker, and the following demonstration program will take 15 seconds to compile on my machine:
func funwrap<T>(_ v: T????????????????????) -> T? {
return (v as? T?) ?? nil
}
let v0: Int = 0
let v1: Int? = nil
let v2: Int?? = 2
let v3: Int??? = nil
let v4: Int???? = 4
let v5: Int????? = nil
let v20: Int???????????????????? = 20
let result: [Int?] = [ funwrap(v0), funwrap(v1), funwrap(v2), funwrap(v3),
funwrap(v4), funwrap(v5), funwrap(v20) ]
print(result)
$ time swiftc demo.swift
real 0m15.087s
user 0m14.762s
sys 0m0.270s
$ ./demo
[Optional(0), nil, Optional(2), nil, Optional(4), nil, Optional(20)]
But isn't the simplest solution to just use as? T?
directly, like this:
// Here, v can have any level of optionality, although there will be a warning
// when flattening if the level is 0, 1 or 2:
let v: Int??????????????????????????????????????????????????????????? = 123
let flattenedToOneLevelOfOptionality = (v as? Int?) ?? nil
print(type(of: flattenedToOneLevelOfOptionality)) // Always prints Optional<Int>
dump(flattenedToOneLevelOfOptionality)