Search code examples
swiftextendtype-alias

In Swift, how to extend a typealias?


I have a typealias:

typealias BeaconId = [String: NSObject]

I'd like to extend it by doing something like:

extension BeaconId {}

But this throws a compile error:

Constrained extension must be declared on the unspecialized generic type 'Dictionary' with constraints specified by a 'where' clause

So I end up doing:

extension Dictionary where Key: StringLiteralConvertible, Value: NSObject {}

Is there a cleaner way to do this?


Solution

  • AFAIK, no.

    Consider the following example:

    typealias Height: Float
    
    extension: Height {
    
    }
    

    Here Height is not a new type, it's just a label for Float so you're just extending Float. If you take a look at Dictionary it's public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible so what you'd be trying to achieve with

    extension BeaconID {}
    

    is adding an extension to Dictionary with specific generic parameters.

    What I would expect that you should be able to do is:

    typealias BeaconID = Dictionary<Key: String, Value: NSObject>
    

    but that also doesn't compile and that's because in Swift you can't typealias partial types (in other words generic types without specific generic parameter types. See here for more info). A possible workaround for typealiasing generic types which is noted below the answer I linked to is

    struct Wrapper<Key: Hashable, Value> {
        typealias T = Dictionary<Key, Value>
    }
    typealias BeaconID = Wrapper<String, NSObject>.T
    

    but even then when you try to extend BeaconID, you get a compiler warning, which finally gets to the heart of the problem:

    "Constrained extension must be declared on the unspecialized generic type 'Dictionary' with constraints specified by a 'where' clause"