Background:
Opaque types (some) were introduced in Swift 5.1 and provide a new way to abstract the return value of a function or property, where the type is known to the compiler but hidden from the user. This is an alternative to protocol existentials (any Protocol), but with a strict binding to a specific type within the function.
Problem: When a function returns a protocol with associatedtype (for example, Sequence), you cannot directly write:
func makeNumberSequence() -> Sequence { ... } // error
Protocol existentials allow returning any implementation but do not guarantee the same type on each call:
func foo() -> any View { ... }
This leads to unpredictability and weak type safety.
Solution: Use opaque result type:
func makeNumbers() -> some Sequence { [1, 2, 3] }
Now the compiler knows the actual return type for sure, but it is hidden externally. This provides performance optimizations, safety, allows for the use of SwiftUI DSL, and simplifies type exchange between modules.
Key features:
Can opaque types be used for storing a value (like class properties)?
No. Opaque types are only applicable for return values of functions or computed properties. For storing a value or an array of values, use existentials (any Protocol).
Can different branches of a single function return different types with some?
No. The compiler requires that both (or all) branches return the same specific type; otherwise, it will give an error:
func foo(flag: Bool) -> some Sequence { if flag { return [1, 2, 3] } else { return ["a", "b", "c"] // error } }
Can some be used to identify the return type between several functions?
No. Each function with some returns its unique hidden type, even if it is effectively the same array. You cannot use the result of one function as a parameter in another if both use some with different protocols or different hidden types.
In the project everything is returned through any Protocol, collections lose type safety, bugs appear during downcasting, and compile-time optimization slows down.
Pros:
Cons:
In SwiftUI design, components return some View, each module clearly defines the internal type. Bundle size is reduced, build time is accelerated.
Pros:
Cons: