tezvyn:

Opaque Types: Hide Implementation, Not Capabilities

AI-drafted, machine-checkedSource: swift.orgintermediate

Opaque types (`some Protocol`) hide a function's concrete return type, exposing only its protocol conformance. This lets you change the implementation later (e.g., from `ReverseCollection`) without breaking client code that just needs `some Collection`.

WHY IT EXISTS APIs evolve. Hard-coding a specific return type, like a ReverseCollection, forces clients to depend on that specific type. If you later find a more efficient implementation, changing the return type becomes a breaking change for your users. Opaque types solve this by hiding the concrete type behind a protocol interface, preserving implementation flexibility.

THE MENTAL MODEL An opaque type is like ordering "a hot beverage" from a café menu. You know you'll get something that conforms to the "hot beverage" protocol (you can sip it, it's warm), but you don't know or need to know if the barista used a French press or an espresso machine. The underlying concrete type is an implementation detail hidden from you.

HOW IT WORKS You declare a function with a return type prefixed by the some keyword, like func makeShape() -> some Shape. From the caller's perspective, they receive a value that is guaranteed to conform to the Shape protocol and can use all its methods and properties. Internally, your function must always return the exact same concrete type (e.g., it must always return a Circle). The compiler knows the real type, but it's "opaque" to the code outside the function's module.

WHEN TO USE IT Use opaque types for return values when you want to provide functionality based on a protocol without exposing the concrete type. This is the default in SwiftUI (e.g., var body: some View) and is excellent for standard library functions that return customized collections. It strengthens the API contract while allowing implementation flexibility.

WHEN NOT TO USE IT Don't use opaque types when the caller needs to know the specific type to do further work. Also, a function with an opaque return type must return the same concrete type from all of its exit points. You cannot have if condition { return Circle() } else { return Square() } if the return type is some Shape, because the compiler can't guarantee a single concrete type is returned.

ONE CANONICAL EXAMPLE The Swift standard library has a reversed() method on collections. An older design might return a concrete ReverseCollection<Self>. A developer might then write code that depends on specific features of ReverseCollection. The modern approach is to return some Collection. This still provides all Collection functionality but hides the specific wrapper, allowing the standard library to change it to a more performant type in the future without breaking user code.

Read the original → swift.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.