I am trying to avoid boilerplate in writing many @propertyWrappers
expected to provide access to the wrappedValue
property via the static subscript
(yes, the one still in beta). By the convention I learned from tutorials, I wish the wrappedValue
property to be unavailable, i.e.
var wrappedValue: SomeType { get { fatalError() } set { fatalError() } }
In my limited Swift vocabulary, I thought this is a problem you could solve via a default implementation to a protocol, as provided via an immediate extension to that protocol. For example, the following trivially works:
protocol ComputedPropertyProtocol {
associatedtype PropertyType
var value: PropertyType { get set }
}
extension ComputedPropertyProtocol {
var value: PropertyType { get { fatalError() } set { fatalError() } }
}
struct AllIGotIsALousyPropertyImplementation: ComputedPropertyProtocol {
typealias PropertyType = UInt
}
let a = AllIGotIsALousyPropertyImplementation()
print(a.value) // Generates "Fatal error" and that’s OK!
Next, I thought of using the same technique to boilerplate-away that wrappedValue
property on my @propertyWrapper
, but this did not work:
protocol SubscriptOnlyPropertyWrapper {
associatedtype PropertyType
}
extension SubscriptOnlyPropertyWrapper {
var wrappedValue: PropertyType {
get { fatalError() }
set { fatalError() }
}
}
@propertyWrapper
struct MyFirstAttempt: SubscriptOnlyPropertyWrapper {
typealias PropertyType = UInt
}
The compiler complains that it can’t find the wrappedValue
property:
expression failed to parse:
error: PropertyWrappers.playground:13:8: error: property wrapper type 'MyFirstAttempt' does not contain a non-static property named 'wrappedValue'
struct MyFirstAttempt<Value>: SubscriptOnlyPropertyWrapper {
^
OK, so I thought generics might nudge the compiler so I tried declaring the @propertyWrapper as a generic:
@propertyWrapper
struct MyFirstAttempt<Value>: SubscriptOnlyPropertyWrapper {
typealias PropertyType = Value
}
...to then clear the error by being explicit about the type, i.e. @MyFirstAttempt<UInt>
. But I never get to that point. The compiler still doesn't see the default implementation for the wrappedValue
property.
Why would @propertyWrapper prevent this technique from working?
Based on my very limited experience with Swift, it seems that @propertyWrapper should have been a protocol (like Codable
), and the language should have gained a new keyword/attribute to limit/allow protocol compliance only for struct rather than class. Something like @structOnly protocol SomeProtocol
(or imagine if something like protocol PropertyWrapper where is struct
would be legal) might have been useful for more than one language feature... instead we got another attribute with narrow scope that seems to alter expected language behavior. Hope I'm missing something obvious which wouldn't be surprising.
Thank you!