How to make protocol describing string-representable enums?

2.5k views Asked by At

I've got a method which calls method of some manager to save int value with some key. My method receives int and some EnumKey enum value as a key, extrudes EnumKey's rawValue and passes it to a manager as a string:

set(value: Int, forKey key: EnumKey) {
    SomeManager.saveIntValueWithStringKey(valueToSave: value, keyToSave: key.rawValue)
}

enum EnumKey: String { 
    case One="first key"
    case Two="second key"
}

I want to make this more generic by allow my method to receive every enum with string raw value instead of EnumKey. In implementation of method I've replaced type of key parameter from EnumKey to GenericKey protocol, and made EnumKey conform this protocol:

 set(value: Int, forKey key: GenericKey) {
    SomeManager.saveIntValueWithStringKey(valueToSave: value, keyToSave: key.rawValue)
}

protocol GenericKey {
    var rawValue: String { get }
}

enum EnumKey: String, GenericKey { 
    case One="first key"
    case Two="second key"
}

But this String, GenericKey looks kinda ugly. I want every string-representable enum to suit automatically without mentioning it conforms to GenericKey protocol in addition to RawRepresentable and String raw type. Something like:

protocol GenericKey: RawRepresentable {
    associatedtype RawValue = String
}

but compiler says "Protocol can be used only as a generic constraint because it has Self or associated type requirements".

What could be an easy way to explain compiler that protocol describes only RawRepresentable things with RawValue of String type?

1

There are 1 answers

0
Daniel On BEST ANSWER

You can define the function as generic, and define the generic type as RawRepresentable with RawValue of type String, like this:

class Test {
    func set<T: RawRepresentable>(value: Int, forKey key: T) where T.RawValue == String {
        print("value \(value), key: \(key.rawValue)")
    }
}

enum EnumKey: String {
    case One="first key"
    case Two="second key"
}

let t = Test()
t.set(value: 3, forKey: EnumKey.One) // prints "value 3, key: first key"