Generics vs protocols as types: when do you write <T: P>(T) vs any P?
Predict first
Does this compile?
func same(_ xs: [any Equatable]) -> Bool {
xs[0] == xs[1]
}
- Yes
- No
Mental model. A generic is a custom-fitted suit. An existential is a one-size-fits-all coat — it fits everything and flatters nothing.
Use generics at API boundaries you control: the compiler keeps the concrete type, specializes the function, and can inline it. Zero existential cost.
Use any P when you need heterogeneity — a stored property, an array of mixed conformers, a plugin list — or when a generic parameter would have to propagate through too much of your API.
The cost of any is real: possible boxing, indirect calls per method, and no specialization of the caller. On a hot path (scroll handler, body, parser loop) that matters.
== needs both sides to be the same concrete type, and two any Equatable values may not be. A generic <T: Equatable>([T]) guarantees it.
| <T: P> | some P | any P | |
|---|---|---|---|
| Compiler knows the type | yes | yes | no |
| Mixed types in one array | no | no | yes |
| Method calls | specialised | specialised | witness table |
| May box on the heap | no | no | yes |
| Self / associated types | yes | yes | limited |
Common traps
- Reaching for
anybecause generics feel noisy. The noise is one type parameter; the cost is permanent dynamic dispatch. - Reaching for generics everywhere. A generic parameter that is always the same concrete type is just indirection with extra steps.
They might follow up with
- What is the “generic parameter creep” problem? One generic parameter forces every caller and wrapper to become generic too. Sometimes an existential at the boundary is the pragmatic choice.
- Can you mix them? Yes — a generic function can take
any Pinternally, and an existential can be opened into a generic context.
Related questions
- 1.4.2 some View vs any View — what is the difference, and why does SwiftUI use some?
- 1.4.4 What is the difference between some P as a parameter (Swift 5.7) and <T: P>?
- 1.4.3 What is the cost of any vs some on a hot path?
some View vs any View — what is the difference, and why does SwiftUI… →