swiftgenericsswift-property-wrapper

Why do we need type annotation in a Swift propertyWrapper?


Consider this @propertyWrapper:

@propertyWrapper struct Capitalized {
    var wrappedValue: String {
        didSet { wrappedValue = wrappedValue.capitalized }
    }
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue.capitalized
    }
}

Using it this way:

struct User {
    @Capitalized var userName: String
}

My question is:

Why do I need to specify a type annotation with the property userName. Isn't the compiler smart enough to deduce that since the wrappedValue of @Capitalized type is String, the property userName can only be of type String.

If I omit the type annotation, I get a compiler error:

Type annotation missing in pattern


Solution

  • The diagnostic here is poor and doesn't point you to the actual issue. The problem is that @Capitalized with no assignment translates into Capitalized(), and there is no such initializer. You can fix this by providing a default initializer:

    @propertyWrapper struct Capitalized {
        ...
    
        init() { self.init(wrappedValue: "") }
    }
    

    With this, your struct is fine:

    struct User {
        @Capitalized var userName
    }
    

    Without the default init(), the following would also be fine, since it calls Capitalized(wrappedValue:):

    struct User {
        @Capitalized var userName = "bob"
    }