I have a following method:
private func returnNilIfEmpty<T: Collection>(_ collection: T?) -> T? {
guard let collection = collection else { return nil }
return collection.isEmpty ? nil : collection
}
I’d like to extend the Collection API to use a computed variable to extract the non-empty value like this:
extension Collection {
var nonEmptyValue: Collection? {
returnNilIfEmpty(self)
}
}
However, I’m getting the error:
Protocol ‘Collection’ can only be used as a generic constraint because
it has Self or associated type requirements
Which is clear, as the outer Collection can be any collection (e.g. an [Int]) while the collection inside the returnNilIfEmpty can be e.g. a String.
The question is how can I enforce the rule that the Collection returned via nonEmptyValue and the one returned via returnNilIfEmpty of the same type, so that I can get rid of this compiler error?
>Solution :
It is appropriate to use Self here:
extension Collection {
var nonEmptyValue: Self? {
returnNilIfEmpty(self)
}
}
If e.g. you did Set([1,2,3]).nonEmptyValue, you’d expect to get a Set<Int>? rather than a general Collection? (you don’t even know what kind of elements this type contains or anything like that!), wouldn’t you?