Skip to content
AgileLogics
6 min read

Opaque and Existential Types: some and any

Prerequisites: Protocol-oriented programming

When you use a protocol as a type, Swift asks you to choose between two meanings with the keywords some and any.

any — "a box that can hold any conforming type"

any Shape is an existential type: a container that can hold a value of any type conforming to Shape, and the specific type can differ from value to value:

protocol Shape {
    func area() -> Double
}
struct Square: Shape { let side: Double; func area() -> Double { side * side } }
struct Circle: Shape { let radius: Double; func area() -> Double { 3.0 * radius * radius } }

var shapes: [any Shape] = [Square(side: 2), Circle(radius: 1)]
shapes.append(Square(side: 3))
print(shapes.map { $0.area() })
[4.0, 3.0, 9.0]

Flexibility has a cost: the value is stored in a box, and each method call is looked up at runtime.

some — "one specific type, which I'm not naming"

some Shape is an opaque type: there is exactly one concrete type behind it, known to the compiler, but hidden from the caller:

func makeTile() -> some Shape {
    Square(side: 4)
}

func totalArea(of shape: some Shape) -> Double {
    shape.area()
}

print(makeTile().area())
print(totalArea(of: Circle(radius: 2)))
16.0
12.0
  • As a return type, some Shape lets a function hide which shape it returns — but it must always return the same type. Returning a Square on one path and a Circle on another is a compile error.
  • As a parameter type, some Shape is shorthand for a generic function: func totalArea<S: Shape>(of shape: S).

Because the compiler knows the real type, some has no boxing overhead and keeps full type information.

You've already used some

Every SwiftUI view declares var body: some View. A view's body is a deeply nested generic type that would be unreadable to write out — some View says "a specific view type; let the compiler work it out".

Which to use

  • some when a single concrete type is involved — the default choice for parameters and return values.
  • any when you genuinely need different types together — a heterogeneous array, or a stored property that can change to a different conforming type.

Common mistakes

  • Returning different types from a some function: function declares an opaque return type 'some Shape', but the return statements in its body do not have matching underlying types. Use any Shape if that's really what you need.