I have created the following code and everything works fine except the definition of TestDBAPI.
When I want to create a type that conforms to the DBAPIProtocol protocol, it is always impossible to generate a type instance that satisfies the generic constraints
Please, how can I define TestNoteFetcher to satisfy the protocol requirement of DBAPIProtocol.
ps: I hope the flexibility of generic definitions can be maintained in DBAPIProtocol
thanks
import Combine
// For Value
public enum WrappedID: Equatable, Identifiable, Sendable, Hashable {
case string(String)
case integer(Int)
public var id: Self {
self
}
}
public protocol BaseValueProtocol: Equatable, Identifiable, Sendable {
var id: WrappedID { get }
}
public struct Note: BaseValueProtocol {
public var id: WrappedID
public var index: Int
public init(id: WrappedID, index: Int) {
self.id = id
self.index = index
}
}
// For Object
public protocol ConvertibleValueObservableObject<Value>: ObservableObject, Equatable, Identifiable where ID == WrappedID {
associatedtype Value: BaseValueProtocol
func convertToValueType() -> Value
}
public final class TestNote: ConvertibleValueObservableObject {
public static func == (lhs: TestNote, rhs: TestNote) -> Bool {
true
}
public var id: WrappedID {
.integer(1)
}
public func convertToValueType() -> Note {
.init(id: .integer(1), index: 0)
}
}
// For Fetcher
public protocol ObjectFetcherProtocol<Object,ConvertValue> {
associatedtype ConvertValue: BaseValueProtocol
associatedtype Object: ConvertibleValueObservableObject<ConvertValue>
var stream: AsyncPublisher<AnyPublisher<[Object], Never>> { get }
}
public final class TestNoteFetcher: ObjectFetcherProtocol {
public typealias ConvertValue = Note
public typealias Object = TestNote
public var stream: AsyncPublisher<AnyPublisher<[TestNote], Never>> {
sender.eraseToAnyPublisher().values
}
public var sender: CurrentValueSubject<[TestNote], Never>
public init(_ notes: [TestNote] = []) {
sender = .init(notes)
}
}
// For API
public protocol DBAPIProtocol {
var notesFetcher: () async -> any ObjectFetcherProtocol<any ConvertibleValueObservableObject<Note>, Note> { get set }
}
// get error in here . Cannot convert value of type 'TestNoteFetcher.Object' (aka 'TestNote') to closure result type 'any ConvertibleValueObservableObject<Note>'
public final class TestDBAPI: DBAPIProtocol {
public var notesFetcher: () async -> any ObjectFetcherProtocol<any ConvertibleValueObservableObject<Note>, Note> = {
TestNoteFetcher([])
}
}
CodePudding user response:
Since your closure returns too many any
s, the compiler got confused & is telling you that TestNoteFetcher
does not conform any ObjectFetcherProtocol
. Generics are your friend, you can use associatedtype
to skip all this code & fix the issue:
public protocol DBAPIProtocol {
associatedtype Fetcher: ObjectFetcherProtocol
var notesFetcher: () async -> Fetcher { get set }
}
public final class TestDBAPI: DBAPIProtocol {
public var notesFetcher: () async -> TestNoteFetcher = {
TestNoteFetcher([])
}
}