I have this function:
func flatten(dict: Dictionary>) -> Dictionary {
v
Try this code in the Playground:
// make sure only `Optional` conforms to this protocol
protocol OptionalEquivalent {
typealias WrappedValueType
func toOptional() -> WrappedValueType?
}
extension Optional: OptionalEquivalent {
typealias WrappedValueType = Wrapped
// just to cast `Optional` to `Wrapped?`
func toOptional() -> WrappedValueType? {
return self
}
}
extension Dictionary where Value: OptionalEquivalent {
func flatten() -> Dictionary {
var result = Dictionary()
for (key, value) in self {
guard let value = value.toOptional() else { continue }
result[key] = value
}
return result
}
}
let a: [String: String?] = ["a": "a", "b": nil, "c": "c", "d": nil]
a.flatten() //["a": "a", "c": "c"]
Because you cannot specify an exact type in the where
clause of a protocol extension, one way you may detect exactly the Optional
type is to make Optional
UNIQUELY conforms to a protocol (say OptionalEquivalent
).
In order to get the wrapped value type of the Optional
, I defined a typealias WrappedValueType
in the custom protocol OptionalEquivalent
and then made an extension of Optional, assgin the Wrapped
to WrappedValueType
, then you can get the type in the flatten method.
Note that the sugarCast
method is just to cast the Optional
to Wrapped?
(which is exactly the same thing), to enable the usage guard
statement.
UPDATE
Thanks to Rob Napier 's comment I have simplified & renamed the sugarCast() method and renamed the protocol to make it more understandable.