ExpressibleByStringLiteral 在函数参数中带有可选值

ExpressibleByStringLiteral with optionals in function parameters

考虑以下枚举

enum Text: Equatable {
    case plain(String)
    case attributed(NSAttributedString)
}

我让它符合ExpressibleByStringLiteral

extension Text: ExpressibleByStringLiteral {
    public typealias StringLiteralType = String
    
    public init(stringLiteral value: StringLiteralType) {
        self = .plain(value)
    }
}

有了这些,我可以像我期望的那样做以下事情:

let text: Text = "Hello" // .plain("Hello")
let text2: Text? = "Hello" // .plain("Hello")

但我收到以下编译器错误:

let nilString: String? = nil
let text3: Text? = nilString // Cannot convert value of type 'String?' to expected argument type 'Text?'

func foo(text: Text?) { /** foo **/ }
let text = "Hello"
foo(text: text) // Cannot convert value of type 'String' to expected argument type 'Text?'

func bar(text: Text?) { /** bar **/ }
bar(text: nilString) // Cannot convert value of type 'String?' to expected argument type 'Text?'

我怎样才能使它们起作用?

我也试过延长 Optional: ExpressibleByStringLiteral where Wrapped: ExpressibleByStringLiteral,但没有用。

ExpressibleByStringLiteral 与自动将 (String, Int) 转换为您的自定义类型无关。 Literal 正好是 "word"string literal)或 12.63Double literal)。 但在您的示例中,let text = "Hello" 常量文本的类型为 String。但是方法 foo 期望类型 Text? 作为参数。

但你可以像这样使用它

foo(text: "Some text")

现在编译器知道它可以将您的字符串文字转换为文本。然后包装成Optional<Text>.