Reputation: 33
import Foundation
protocol ProtocolA: Codable {
var var1: String { get }
}
struct Type1: ProtocolA {
var var1: String
var var2: Int
}
struct Type2: ProtocolA {
var var1: String
var var2: Bool
}
func encode<T: ProtocolA & Encodable>(object: T) throws -> Data {
return try JSONEncoder().encode(object as! T.Type)
}
Putting the above in a playground results in error: argument type 'T.Type' does not conform to expected type 'Encodable'
Why does this happen when I am saying that T
has to conform to Encodable
?
Upvotes: 1
Views: 69
Reputation: 921
Your compiler is actually complaining about the type cast your doing at the end which is converting object
to the metatype
of T, in your example either Type1.Type
or Type2.Type
.
From the encoding perspective, what the compiler needs to know is the model confirms to Encodable
which is implicit in the T: Codable
statement.
import Foundation
protocol ProtocolA: Codable {
var var1: String { get }
}
struct Type1: ProtocolA {
var var1: String
var var2: Int
}
struct Type2: ProtocolA {
var var1: String
var var2: Bool
}
func encode<T: Codable>(object: T) throws -> Data {
return try JSONEncoder().encode(object)
}
let type2 = Type2(var1: "test1", var2: true)
print(type2)
Upvotes: 1
Reputation: 299663
return try JSONEncoder().encode(object as! T.Type)
This means to convert object
to the metatype of T
. The type of the type. For example, 1 is an Int. But "Int" itself has a type, which is Int.Type
, which is a metatype. Metatypes do not conform to Encodable.
You meant:
return try JSONEncoder().encode(object as! T)
But you really just meant:
return try JSONEncoder().encode(object)
since object
is always of type T. That's its explicit type from the function signature. Since you also don't rely on ProtocolA for this algorithm, this all boils down to:
func encode<T: Encodable>(object: T) throws -> Data {
return try JSONEncoder().encode(object)
}
Upvotes: 3