What is the difference between some and any in Swift?
TL;DR
some Protocol means "one specific type that conforms. The compiler knows which one, the caller does not."
any Protocol means "a box that can hold any conforming type, and it can change at run time."
some is faster and keeps type information. any is more flexible. Prefer some and use any when you need mixed types.
some: one fixed hidden type
protocol Shape { func area() -> Double }
struct Circle: Shape { let r: Double; func area() -> Double { .pi * r * r } }
struct Square: Shape { let s: Double; func area() -> Double { s * s } }
func makeShape() -> some Shape {
Circle(r: 1) // always a Circle
}The function must return the same type on every path.
func badShape(round: Bool) -> some Shape {
if round { return Circle(r: 1) }
return Square(s: 1) // error: different types
}SwiftUI uses this everywhere: var body: some View. The real type is a long nested generic type that you never want to write.
any: a box for many types
func randomShape(round: Bool) -> any Shape {
round ? Circle(r: 1) : Square(s: 1) // fine
}
let shapes: [any Shape] = [Circle(r: 1), Square(s: 2)]
let total = shapes.reduce(0) { $0 + $1.area() }any Shape is an existential. It stores the value in a box with a pointer to the type's witness table.
some in parameters
Since Swift 5.7, some in a parameter is short syntax for a generic.
func describe(_ shape: some Shape) { print(shape.area()) }
// same as
func describe<S: Shape>(_ shape: S) { print(shape.area()) }Compare with any:
func describeAny(_ shape: any Shape) { print(shape.area()) }Both work for one value. The generic version can be specialized and is usually faster.
Side-by-side
some Shape | any Shape | |
|---|---|---|
| Meaning | One concrete type, hidden | Any conforming type, boxed |
| Decided by | The implementation (return) or caller (parameter) | Run time |
| Can change per call path? | No | Yes |
| Mixed array? | No | Yes |
| Dispatch | Static (can specialize) | Dynamic (witness table) |
| Cost | No box | Existential box, maybe heap allocation |
| Keeps associated types? | Yes | Erased, unless you use any P<T> |
Associated types and Self
some keeps full type information. So it works well with protocols that have associated types.
func firstElement(of c: some Collection<Int>) -> Int? { c.first }With any, the associated type is erased. Some methods become unusable.
let a: any Equatable = 1
let b: any Equatable = 2
// a == b // error: Swift cannot prove both are the same typeThe cost of any
An existential container has a small inline buffer (three machine words). Bigger values are stored on the heap. Every call goes through a table. Inside hot loops this matters.
That is why the Swift team added the any keyword. It makes the cost visible in code.
Is any required?
For protocols with associated types or Self requirements, yes. For simple protocols, writing plain Shape as a type still compiles in Swift 6. The upcoming feature ExistentialAny makes any required everywhere. Writing any always is a good habit.
How to choose
- Start with
some(or a generic). - Use
anywhen you need different types in one collection or one variable. - Use
anyfor stored dependencies when you want to swap them in tests, likelet service: any UserService.
Common follow-up questions
- What is an opaque type? The formal name for
somein a return position. The function hides the type, but the compiler still knows it. - Can a stored property be
some? Yes, if it has an initial value:var shape: some Shape = Circle(r: 1). - How do you go from
anyback to a concrete type? Useas?to cast, or pass it to a function that takessome P. Swift opens the existential for you (since 5.7). - Why does
bodyusesome Viewand notany View? SwiftUI needs the exact type to diff views efficiently.any Viewwould hide it. - What is
AnyView? A type-erased wrapper. It works, but SwiftUI loses type information, so prefer@ViewBuilderandsome View.