Возможно, вы захотите дать этому протоколу более подходящее имя, но я не предвижу никаких проблем с ним как есть, если только вы не создаете свои ExpressibleByNilLiteral
типы, которые не переносятся.
protocol ExpressibleByNilLiteral: Swift.ExpressibleByNilLiteral {
associatedtype Wrapped
}
extension Optional: ExpressibleByNilLiteral { }
func onlyCallableByAnOptional<Optional: ExpressibleByNilLiteral>(_ optional: Optional) -> Optional.Wrapped? {
optional as? Optional.Wrapped
}
Рекомендация: используйте инициализатор. (Недостатком является то, что метка аргумента необходима для устранения неоднозначности, но мне лично нравится ясность из-за того, как странен этот случай. То есть Swift позволяет легко установить, что что-то не необязательно, но не наоборот.)
extension Optional: ExpressibleByNilLiteral {
init<Optional: ExpressibleByNilLiteral>(optional: Optional) where Optional.Wrapped == Wrapped {
self = optional as? Wrapped
}
}
+
if let v = Optional(optional: i) { // ERROR, as was desired.
print("integer \(v)")
}
if let v = Optional(optional: oi) { // OK, as expected.
print("optional integer \(v)")
}