Hi all, I am using TCA and would like to add a dependency which wraps around UserDefaults in a type safe manner. Normally I might have its implementation look like this:
public struct PropertyPersistence {
public func fetchProperty<T: Codable>(with key: String) -> T? {
fatalError("implementation here")
}
public func set<T: Codable>(property: T, with key: String) {
fatalError("implementation here")
}
}
I would also normally wrap this in a protocol so that I can easily control it when testing. When translating this to the TCA environment, however, I run into an issue with generics. If I create this as a struct with closures as properties, I lose the ability to have generic implementations. I could add them to the type itself, but then my environment would need to have an entry for each specific type:
public struct PropertyPersistence<T: Codable> {
public var fetchProperty: (String) -> T?
public var setProperty: (T, String) -> Void
}
extension PropertyPersistence {
static var live: Self(fetchProperty: { ... }, setProperty: { ... })
}
struct Environment {
var propertyPersistenceString: PropertyPersistence<String>
var propertyPersistenceInt: PropertyPersistence<Int>
....
}
I could see one benefit here being having a very clear dependency graph....but it still seems a bit overly restrictive and redundant.
Does anyone have any ideas around how to avoid keeping multiple variants of a generic dependency in the environment?