Articles, podcasts and news about Swift development, by John Sundell.

Using Self to refer to enclosing types

Published on 08 Jan 2020

Swift includes a number of features that can help us make our code more concise and easier to read, such as its type inference capabilities, type aliases, and the way that types can be referred to within their own declarations and extensions.

For example, let’s say that we wanted to extend a generic type, such as the PublishingStep<Site> type from Publish, with a new static factory method. When declaring our method, we could of course type out PublishingStep<Site> every time that we want to refer to the extended type itself, like this:

extension PublishingStep {
    static func group(
        _ steps: [PublishingStep<Site>]
    ) -> PublishingStep<Site> {
        PublishingStep<Site>(...)
    }
}

However, that’s quite verbose, and not in the way that makes our code easier to read or understand — quite the opposite. Thankfully, when extending a generic type, we don’t have to type out its complete signature, all we need is the name of the type itself — and the compiler will infer the rest:

extension PublishingStep {
    static func group(
        _ steps: [PublishingStep]
    ) -> PublishingStep {
       PublishingStep(...)
    }
}

That’s definitely better, and functionally the same as our initial implementation — but as of Swift 5.1, we can go one step further. Thanks to the improvements made to the Self alias, we can now use that to refer to any method or property’s enclosing type in a really compact manner, like this:

extension PublishingStep {
    static func group(_ steps: [Self]) -> Self {
       Self(...)
    }
}

Note how Self can even be used when creating a new instance of our type.

While compact code isn’t always better code, in this case, using Self has definitely made our code easier to read — without sacrificing any of its functionality or meaning. It’s a great tool to keep in mind when working with types that have longer names, or complex generic types.