If you're able to use Swift 6, I would recommend using the standard Mutex type over any manually-written wrappers. Even if it were possible to back a property wrapper with a let storage property, I would still strongly recommend against trying to hide the lock-taking behavior, since it is otherwise impossible to reason about the actual atomicity of updates. You can explicitly write:
private static let basket: Mutex<Set<T>> = Mutex([])
and update that value from any thread with:
basket.withLock { $0.insert(element) }