Reputation: 61774
I have created typealias
:
typealias Multilang = [String: Any]
Now I would like to extend that Dictionary with property localized
. Is it possible?
How do I need to use it?
let dictionary: Multilang = ["en": "b", "pl": "d"]()
let value = dictionary.localized
I try to do it like this:
extension Dictionary where Dictionary: Multilang {
var localized: String {
print("self: \(self)")
return "hello"
}
}
but it doesn't work. Why?
Type 'Dictionary(Key, Value)' constrained to non-protocol, non-class type 'Multilang' (aka 'Dictionary(String, Any)')
Upvotes: 2
Views: 531
Reputation: 4391
For Swift 3 and above you can try this method to extend a dictionary of type [String: Any]
.
extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
// Your extension code
var localized: String {
print("self: \(self)")
return "hello"
}
ExpressibleByStringLiteral
is a protocol that String
and StaticString
types conform to.
You cannot apply it just to the type alias, because Multilang
is just a label for [String:Any]
, so even if you could extend it, it would extend all dictionaries of this type anyway.
Upvotes: 1
Reputation: 42139
It is (unfortunately) not possible to use typealias
in this way, because it does not create a new type. For example, you can have typealias Foo = [String: Any]
and typealias Bar = [String: Any]
, but Foo
and Bar
still both the same type.
So either you have to extend all [String: Any]
dictionaries, or you need to create a wrapper type (you also cannot subclass Dictionary
because it is a struct
). For example:
struct Multilang<Element> {
var dictionary: [String: Element]
var localized: Element? {
return dictionary[currentLanguage]
}
}
The downside is you need to define all the wrapper methods and properties that you want to use through multilang.foo
syntax, but if it suffices to have just multilang.localized
, you can do all the rest through multilang.dictionary.foo
.
You can also implement ExpressibleByDictionaryLiteral
to make creating these objects easy:
extension Multilang: ExpressibleByDictionaryLiteral {
init(dictionaryLiteral elements: (String, Element)...) {
dictionary = .init(elements) { $1 }
}
}
let multilang: Multilang = [ "en": "English", "pl": "Polish" ]
Upvotes: 3
Reputation: 4621
You can write an extension like this:
extension Dictionary where Key == String, Value == Any {
var localized: String {
print("self: \(self)")
return "hello"
}
}
or:
extension Dictionary where Dictionary == Multilang
Upvotes: 2