Howto: DRY way to capitalized String rawValue enum case name?

This is the end result I want:

enum Personel: String, CaseIterable {
    case teddy = "Teddy"
    case kitty = "Kitty"
    case bonny = "Bonny"
    case smokey = "Smokey"
}

Is there anyway I can avoid having to hand assign capitalized rawValue? Just do this:

enum Personel: String, CaseIterable {
    case teddy
    case kitty
    case bonny
    case smokey
}

Of course I can just capitalize the case value itself. But seems it's Swift style to use lower case. Can I have both follow good code style and get capitalized rawValue?

would be nice if I can override rawValue getter and insert my code...

2 Likes

You can. Just implement RawRepresentable. You have to go both directions though.

It would be nice if the various key conversions from the decoders were generally available.

2 Likes

Does it have to be the rawValue? This might work for you.

enum Personel: String, CaseIterable {
    case teddy
    case kitty
    case bonny
    case smokey

    var displayName: String {
       return rawValue.capitalized
    }
}
6 Likes

With RawRepresentable, I still have to manually spell out the capitalized form of each case rawValue...with even more code than simply hand assigning the String rawValue of each case.

For now, I just add a getter func to the enum to return the capitalized rawValue.

Yes, that's what I did, too. Thank you!

from experience, you almost never want to do this. You don't want to tie the prosaic representation to the Swift identifier or else you're eventually going to end up with

enum 
{
    case fooBar  // -> 'FooBar', not 'Foo Bar'
    case _2D     // -> '_2D', not '2D'
    case oreilly // -> 'Oreilly', not 'O'Reilly'
}

a computed String property with a switch over self is verbose, but it's almost always what you're going to end up with anyway.

8 Likes

I think I've found a way...

protocol PascalCasedString: CaseIterable, RawRepresentable where RawValue == String {}

extension PascalCasedString {
    init?(rawValue: String) {
        guard let match = Self.allCases.first(where: { $0.rawValue == rawValue }) else {
            return nil
        }
        self = match
    }
    var rawValue: String {
        let caseDescription = String(describing: self) // likely camel-Cased
        return caseDescription.prefix(1).uppercased() + caseDescription.dropFirst()
    }
}

enum MessageName: PascalCasedString {
    case someMessage
}
1 Like