Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 945
abc123 Avatar asked Nov 18 '15 03:11

abc123


People also ask

Can you extend a function in Swift?

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.

How do you extend a string in Swift?

Creating an extension in Swift Creating extensions is similar to creating named types in Swift. When creating an extension, you add the word extension before the name. extension SomeNamedType { // Extending SomeNamedType, and adding new // functionality to it. }

What does Typealias do in Swift?

A type alias allows you to provide a new name for an existing data type into your program. After a type alias is declared, the aliased name can be used instead of the existing type throughout the program. Type alias do not create new types. They simply provide a new name to an existing type.

What is the point of extension Swift?

A Swift extension allows you to add functionality to a type, a class, a struct, an enum, or a protocol.


2 Answers

Update at the time of Swift 4.2: you can now do this

Example:

typealias KeyedNumbers = [String: Int]

extension KeyedNumbers {
    func squaredValue(forKey key: String) -> Int {
        return self[key]! * self[key]!
    }
}

With that (pretty useless) extension in place, you can do this:

let pairs = ["two": 2, "three": 3]
print("2 squared =", pairs.squaredValue(forKey: "two"))

And it will print

2 squared = 4

like image 50
epologee Avatar answered Oct 25 '22 21:10

epologee


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"

like image 37
barndog Avatar answered Oct 25 '22 21:10

barndog