Swift version: 5.10
Protocols with associated types are a powerful, if somewhat treacherous, feature of Swift. Sometimes it’s fair to say that the only winning move is not to play – i.e., to avoid them entirely – but if that isn’t the case you are sometimes likely to find yourself facing a difficult error: “protocol can only be used as a generic constraint because it has Self or associated type requirements.”
As an example, here’s a protocol with an associated type:
protocol Identifiable {
associatedtype ID
var id: ID { get set }
}
So, whatever type wants to conform to Identifiable
must state which type they use to identify themselves. We could create two instances of such types like this:
struct Person: Identifiable {
var id: String
}
struct Website: Identifiable {
var id: URL
}
That is, people identify themselves using a String
, and websites use a URL
. So far, so easy. However, if you want to write a function using Identifiable
as parameters you’ll hit a problem. For example, you might try to write a function that compares two instances of Identifiable
like this:
func compareThing1(_ thing1: Identifiable, against thing2: Identifiable) -> Bool {
return true
}
That will issue the error “protocol 'Identifiable' can only be used as a generic constraint because it has Self or associated type requirements.”
The reason for the error is simple enough: although thing1
and thing2
being passed into the function both conform to Identifiable
that doesn’t make them usable in the same way – the id
of a person and the id
of a website are completely different types, so there’s no meaningful way you can use them together.
As the error says, this protocol can be used only as a generic constraint. That’s actually pointing us to the solution here: if we use Identifiable
as a generic constraint then we can tell Swift not only that thing1
and thing2
conform to the protocol but also that they are actually the same type.
func compareThing1<T: Identifiable>(_ thing1: T, against thing2: T) -> Bool {
return true
}
That code fixes the problem, because Swift has enough information to know how you plan to use thing1
and thing2
.
GO FURTHER, FASTER Unleash your full potential as a Swift developer with the all-new Swift Career Accelerator: the most comprehensive, career-transforming learning resource ever created for iOS development. Whether you’re just starting out, looking to land your first job, or aiming to become a lead developer, this program offers everything you need to level up – from mastering Swift’s latest features to conquering interview questions and building robust portfolios.
Available from iOS 8.0
This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.
Link copied to your pasteboard.