Alternatively I was thinking about how to use new @propertyWrapper to wrap these properties with a default value. However using a @propertyWrapper appears to break the struct's ability to comply with Codable.
Currently, the only way to do this is to implement init(from:) to assign the default value you need. Codable synthesis is conservative and doesn't fall back to assigned default values to prevent accidental silent data loss/corruption, so you have to be fully explicit if that's what you expect.
I'm don't believe a property wrapper would be enough here, given that decoders throw on missing data (and I don't think a property wrapper would be able to intercept that, since IIRC property wrappers are meant to encode as the underlying value type), but I haven't fully sketched out that possibility.
In the future, having a way to influence Codable synthesis would likely be the most resilient option.
Ok. Thanks for saving me from going down the property wrapper path. Definitely would be nice to see something between full automatic synthesis and having to handle init manually, especially when my real struct is pretty massive.
If I could override just the values I care about and pass the reset onto auto synthesis that'd be nice too (maybe I can and I've missed that).
But what I've proposed above seems the most logical to me in terms of making synthesis behave like you think it would (values that are present are used but overwritten by those found in the serialized data). I guess it'd be different with let values so maybe my idea isn't the best.