Swift: Attempting to Understand Type Erasure

At the try! Swift Conference in Tokyo, @purpleyay gave a mind-blowing talk on Type Erasure (full video and slides here). I’m honestly still trying to wrap my head around it, and especially the use-cases, but for now, I wanted to write down the example from the talk to keep in my mind and refer to later when it suddenly fits the problem I’m solving.

The Problem

Let’s say you have a simple Pokemon protocol and implementations as follows:

It’s all fun and games, until you want to do a little abstraction. Let’s say you don’t care about what type of Pokemon is doing the attack.

This is a super common scenario, but unfortunately, protocols with associated types do not allow this 😭
Pikachu

The Solution

This is where Type Erasure comes in. After all, we want to erase the explicit Pikachu type, and use the abstract Pokemon type:

Updated Solution

As commenter @salabaha pointed out below, there is an even simpler way to do Type Erasure that works without having to explicitly set the type of the associated type!

Love this!

Update: Unfortunately, this is not Type Erasure – it’s the same as the original solution of having a specific Pokemon in the first place:

And we still cannot make an array of Pokemons with the same power:

Still getting the hang of this 🙈

Conclusion

This still feels like an overly complex fix for something that should just work and hopefully it will in the future. For now, this is a super good pattern to know when working with protocols with associated types.

Oh, and as @allonsykraken points out, one example of where this is used is in Swift’s AnySequence implementation.

Enjoy your new Type Erasure power 💪

Join me for a Swift Community Celebration 🎉 in New York City on September 1st and 2nd. Use code NATASHATHEROBOT to get $100 off!

Enjoy the article? Join over 17,500+ Swift developers and enthusiasts who get my weekly updates.

  • Basel Farag

    Oh my goodness. I was banging my head on my desk about this *just* last night. Cheers, Natasha.

  • finneycanhelp

    Small typo “do no allow this” (not*). Btw, my young son loves the article too! 😊👏

  • salabaha

    Here is even simpler way to design AnyPokemon struct

    struct AnyPokemon {
    private let _pokemon: P
    init(_ pokemon: P) {
    _pokemon = pokemon
    }

    func attack() -> P.Power{
    return _pokemon.attack()
    }
    }

  • salabaha

    Here is even simpler way to design AnyPokemon struct.

    struct AnyPokemon {
    private let _pokemon: P
    init(_ pokemon: P) {
    _pokemon = pokemon
    }

    func attack() -> P.Power{
    return _pokemon.attack()
    }
    }

    • Yes, but it doesn’t work for the same reason the initial version didn’t work.

      • salabaha

        This is strange. Here is the screen shot from the playground. It all compiles and working. Or I’m getting you wrong?

        • Ah – got it! Was still stuck with the way I was doing it. Super cool. Will add this as an update!

        • Ok – wrote it up and got some feedback. See comments above.

          • salabaha

            Natasha, comments above are reasonable. Sorry for the confusion. I just introduced simplified solution without thinking about the idea behind this code. With a little research I found nice post abut generic protocols in swift explaining what type erasure is. Here is the link: http://krakendev.io/blog/generic-protocols-and-their-shortcomings.

  • Apokrupto

    I think you’d love Rob Napier’s talk at this year’s dotSwift conference. He discusses type erasure and reduces the problem until hitting a more compact solution. Video is here http://www.thedotpost.com/2016/01/rob-napier-beyond-crusty-real-world-protocols

  • Robert Edwards

    Hey Natasha,

    Thanks for highlighting this topic!

    After reading Rob Napier’s two posts on type erasure usage in the standard library (http://robnapier.net/erasure http://robnapier.net/type-erasure-in-stdlib), I decided to apply this technique to your Pokemon example.

    Picking up where you left off after // power types

    This allows for the flexibility to do the following:

  • Hey Natasha,

    Thanks for highlighting this topic!
    After reading Rob Napier’s two posts on type erasure usage in the standard library I decided to apply this technique to your Pokemon example.

    Picking up where you left off after // power types

    This allows for the flexibility to do the following:

  • Anthony Miller

    Your updated solution still leaves your pokemon property of type `AnyPokemon.

    I don’t understand how this really qualifies as TypeErasure.

    • I’m wondering the same thing too. Not really sure how I should go about this erasure when I need any pokemon as an instance variable in a class.

  • tralejbus

    If you need type erasure, that’s a good sign that you’re doing it not the Swift way. Often an extension can completely remove this necessity.