В Swift, как расширить титалиас?

У меня есть typealias:

typealias BeaconId = [String: NSObject]

Я хотел бы расширить его, выполнив что-то вроде:

extension BeaconId {}

Но это вызывает ошибку компиляции:

Ограниченное расширение должно быть объявлено в неспециализированном родовом "Словаре" с ограничениями, указанными предложением "where"

Итак, я делаю:

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

Есть ли более чистый способ сделать это?

Ответ 1

AFAIK, no.

Рассмотрим следующий пример:

typealias Height: Float

extension: Height {

}

Здесь Height не является новым типом, это просто метка для Float, поэтому вы просто расширяете Float. Если вы посмотрите на Dictionary it public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible, что бы вы пытались достичь с помощью

extension BeaconID {}

добавляет расширение к Dictionary с помощью определенных общих параметров.

Что я ожидаю, что вы сможете это сделать:

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

но это также не компилируется, и что, поскольку в Swift вы не можете вводить неполные типы типов (другими словами, общие типы без конкретных типов общих типов. См. здесь для получения дополнительной информации). Возможным обходным путем для типов, генерирующих общие типы, которые указаны ниже ответа, с которым я связан, является

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

но даже тогда, когда вы пытаетесь расширить BeaconID, вы получаете предупреждение о компиляторе, которое, в конечном итоге, попадает в суть проблемы:

"Ограниченное расширение должно быть объявлено в неспециализированном родовом" Словаре "с ограничениями, указанными в предложении" где "

Ответ 2

Обновление во время Swift 4.2: теперь вы можете сделать это

Пример:

typealias KeyedNumbers = [String: Int]

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

С этим (довольно бесполезным) расширением вы можете сделать следующее:

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

И это будет печатать

2 в квадрате = 4