Swift icon Swift

Swift Opaque Result Types

WWDC 2019 has just passed and a lot of new features were introduced! The one that really got my attention was Swift 5.1 new opaque result type. This blogpost will try to explain what this new type does using examples from SwiftUI! 

Opaque Result Types

The opaque result type helps you return a specific generic type without specifying which type with the help of the word “some”. To help clarify this explanation, I will provide you with some examples. One of the best examples I found is using the new SwiftUI from Apple. If you make a view you have to implement the View protocol and specify a body like this:
Note the “some” keyword, this means we’re returning an opaque result type.

struct Example: View {
    
    var body: some View {
        return Text("Hello world")
    }
}

Within this body property, we can define anything, as long as it implements the View protocol, the cool part is, we do not have to specify which View, the compiler will figure it out for us. But what does it exactly do? For that we will take a closer look at the View protocol, the implementation is:

public protocol View : _View {

    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    associatedtype Body : View

    /// Declares the content and behavior of this view.
    var body: Self.Body { get }
}

As you can see, the View protocol has an associated type property and the body is returning this associated type. Prior to Swift 5.1, you had to specify what the associated type would be if you implement the protocol like this:

struct Example: View {
    typealias Body = Text

    var body: Example.Body {
        return Text("Hello world")
    }
}

Which would mean every time we change our body variable, we also have to adjust our associated type. What is more, if we were returning a lot of items, we have to specify them all like this:

struct Example: View {
    typealias Body = VStack<TupleView<(Text, Text)>>

    var body: Example.Body {
        return VStack {
            Text("Hello world")
            Text("This is an example")
        }
    }
}

This could get horrible long if we have a big view and a big hassle if we only changed or added one value. You could say why not return just the protocol View? Well, because the View has an associated type, we get a compiler error because Swift does not know which associated type is being returned here.

Showing the generic constraint error fro, associated type requirements.

Luckily the opaque result type will resolve this for us! Using the “some” keyword we tell Swift we are returning a specific type which conforms to View! For example if we would return VStack, the compiler knows it will be a VStack that implemented the View protocol. If we change this value to Text, the compiler automatically sees that now the body is of type Text which implemented the View protocol! We did not have to specify the associated type or the generic construct! 

struct Example: View {

    var body: some View {
        return VStack {
            Text("Hello world")
            Text("This is an example")
        }
    }
}

For more information about the Opaque Result Type, I would recommend you read the proposal [0244].