In Xcode with Swift, if you use a lowercase enum for namespacing constants you get ideal syntactic sugar and bonus syntax highlighting at call sites.

The lowercase-enum trick composes well* with static dynamic member lookup + static key paths to build a platform-agnostic design system full of constants that can then get projected to the platform type.

*subjective

I made a document on my website to catalog the lowercase enum idea.

https://kylehugh.es/documents/swift-namespace-lowercase-enum/

Namespaces in Swift Using Lowercase Enums

A technique for creating namespaces in Swift using caseless lowercase enums.

@kyle Love this. Short and to the point!
@mattiem your flattery won’t work on me

@kyle @mattiem would it be too much additional work to do this instead?

extension TimeInterval {
public static let animation = Animation()
public enum Animation {
public let `default`: TimeInterval = 0.25
public let minorTweak: TimeInterval = 0.15
public let pop: TimeInterval = 0.35
}
}

@miguelcabeca @mattiem Not too much work, no.

But, technically, this needs to be a `struct` so it can be instantiated. And then it needs a private initializer to communicate that it shouldn't be instantiated outside of this limited scope. So now this has become a many-step pattern every time we want to replicate it. Things to remember, things to get wrong, levels of misdirection.

What I proposed, although it has its own edges, minimizes the levels of misdirection and the number of rules.

@kyle @mattiem right, I missed that. I see the elegance of the solution now, but the breaking of convention makes me uneasy. Probably enough to keep me away from it. Thank you for taking the time to write it up though!

@kyle @mattiem ok, I gave it one more try, this time in front of a computer in Xcode instead of typing in my phone. What about this?

extension TimeInterval {
public static let animation = Animation.self
public enum Animation {
public static let `default`: TimeInterval = 0.25
public static let minorTweak: TimeInterval = 0.15
public static let pop: TimeInterval = 0.35
}
}

@miguelcabeca @mattiem That’s clever. Its implementation still has more ceremony and is unconventional in its own right—a middleman property that exists to exposes a type.

That’s how I ended up where I did: every solution to this “problem” is unconventional, and I found the friction from remembering the implementation patterns to be slightly too much, at scale. With my proposal (?), one has to get over one piece of misconvention, but everything else is self-evident and memory-free.

@kyle @mattiem yes, you’re right. I think these are all unconventional solutions to have our way in avoiding using a top level enum for holding all the constants and just using it in the call site like this: Animation.duration
The fact that we want to use .animation.duration takes us into one of two paths: either define an embedded lower case type, breaking the capital type convention, or expose an embedded Type through a lowercase property which doesn’t break (or follow) any conventions but it’s quite strange. Pick your poison I guess. 🤷‍♂️
@miguelcabeca @kyle @mattiem Have been avoiding chiming in because I didn’t want to harshen anyone’s vibes, but I think generally this solution is what I would recommend. It creates the same namespace/chaining/property syntax, but with the ability to provide intermediate state which you would otherwise have to resort to `static` for if you use an enum.
@mergesort @miguelcabeca @mattiem There are a lot of ways to get that syntax with more features but none, IMO, whose cognitive load is so low. When I have 150 of these, maintaining identical structs-and-properties-and projections, or whatever the implementation is, weighs on me in an intangible way.
@kyle @miguelcabeca @mattiem That’s fair. FWIW I’ve moved from the enum approach you wrote about to structs over the years and overall have seen negligible mental overhead, but everybody’s different.
@mergesort @miguelcabeca @mattiem I’m like a Ferrari, I need high octane gas.
@kyle @miguelcabeca @mattiem Makes sense. You would go from 0 to 60 in record time but can’t drive on most streets.
@kyle Big fan of caseless enums for namespacing in the first place, so I’m onboard with this. The lowercase convention is an interesting touch. It would take some getting used to, but I do agree it’s a good way to communicate the intent where it’s used.