>我有一个通用的 REST 请求:
struct Request<T> {…}
T
是请求的返回类型,例如:
struct Animal {…}
let animalRequest = Request<Animal>
let animal: Animal = sendRequest(animalRequest)
现在我想表达泛型类型必须符合Decodable
,以便我可以解码来自服务器的 JSON 响应:
struct Request<T> where T: Decodable {…}
struct Animal: Decodable {…}
这是有道理的并且有效——直到我到达一个没有响应的请求,一个Request<Void>
.编译器对此不满意:
Type 'Void' does not conform to protocol 'Decodable'
我试图通过将Decodable
一致性添加到Void
来解决这个问题的恶作剧尝试很快被编译器发现:
extension Void: Decodable {…} // Error: Non-nominal type 'Void' cannot be extended
将请求泛型放在返回类型上感觉是正确的。有没有办法让它与Void
返回类型一起使用?(例如,只在服务器上创建某些内容而不返回任何内容的请求。
一个简单的解决方法是引入一个自定义的"no-reply"类型来替换Void
:
struct NoReply: Decodable {}
不符合Decodable
的Void
是不可能的。Void
只是空元组的类型别名,()
,元组目前无法符合协议,但它们最终会。
我发现有时其他类型的其他编码对象可以解码为 NoReply.self。例如,自定义错误类型(枚举(可以是。
本案的游乐场示例:
enum MyError: String, Codable {
case general
}
let voidInstance = VoidResult()
let errorInstance = MyError.general
let data1 = try! JSONEncoder().encode(voidInstance)
let data2 = try! JSONEncoder().encode(errorInstance)
let voidInstanceDecoded = try! JSONDecoder().decode(VoidResult.self, from: data1)
//VoidResult as expected
let errorInstanceDecoded = try! JSONDecoder().decode(MyError.self, from: data2)
//MyError.general as expected
let voidInstanceDecodedFromError = try! JSONDecoder().decode(VoidResult.self, from: data2)
//VoidResult - NOT EXPECTED
let errorInstanceDecodedFromVoid = try! JSONDecoder().decode(ScreenError.self, from: data1)
//DecodingError.typeMismatch - Expected
所以我的建议是添加"NoReply 的唯一性(zoul 的答案((:
struct VoidResult: Codable {
var id = UUID()
}
let voidInstanceDecodedFromError = try! JSONDecoder().decode(VoidResult.self, from: data2)
//DecodingError.typeMismatch - Now its fine - as expected