In Swift, how to extend a typealias?

2019-02-16 13:24发布

问题:

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?

回答1:

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"