Understanding opaque types in Swift
Explore opaque types in Swift for building flexible and type-safe abstractions.
09 Dec 2024 · 3 min read
Swift is a type-safe language, meaning every variable and constant has a defined type that the compiler checks to prevent type-related errors. While this is beneficial, there are times when complex return types make function signatures lengthy and harder to read, especially when working with protocols or generics.
Opaque types offer a powerful solution. By returning an opaque type instead of an explicit type, we can hide the exact underlying type of a value while maintaining type safety.
In this article, we’ll walk through what opaque types are, how to use them, and when they’re most useful in Swift programming.

What is an opaque type?
In Swift, an opaque type is represented by the some keyword, which we place before a type in a function’s return signature. By using some, we specify that a function returns a type that conforms to a given protocol without revealing the exact underlying type:
func shape() -> some Shape {return Circle()}
Practical uses of opaque types
Simplifying complex return types
In SwiftUI, opaque types allow us to hide specific view types. This is beneficial because SwiftUI views often contain complex types that are nested or generic.
func loginView() -> some View {VStack {Text(...)Button(...)}}
Here, the function hides the exact type of the view, allowing flexibility and avoiding a complex return type.
Combining with protocols with associated types
Protocols with associated types aren’t always usable as standalone types. For instance:
protocol Container {associatedtype Itemfunc getItem() -> Item}func makeContainer() -> Container {// This won’t work, as Container has an associated type.}
In the example above, we cannot just return Container, since it has an associated type. Instead, we can use an opaque type to specify that the function returns a type conforming to Container, without needing to specify the associated type:
func makeContainer() -> some Container {return // Return a concrete type conforming to Container}
Limitations of opaque types
Opaque types provide great flexibility, but there are some limitations:
- Single Concrete Type: Opaque types only work when a function returns a single concrete type. We cannot return multiple different types as opaque types within the same function.
- No External Type Information: Since the exact type is hidden, the caller cannot make assumptions about the underlying type—only that it conforms to the declared protocol.
For example, if we try to return multiple different types, we’ll get a compiler error:
func shape() -> some Shape {if someCondition {return Circle()} else {return Square() // Error: Return type must be the same}}
To resolve this, both branches of the function must return the same concrete type.



Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips



