TL;DR
Key paths have a lot of room to grow. I fear that coming up with different types, like CasePath, for what can ultimately be a key path, will only fragment the language. Instead, we could allow no-payload enum cases and static properties in key paths, as a straightforward extension. Then, if all goes well, we could explore how functions could fit into the key path model, to resolve key paths' inconsistencies.
Perhaps I've missed something, but integration into the existing key path feature seems more consistent with the language:
// Enums cannot currently refer to cases
let colorConstructor: KeyPath<Color.Type, Color> = \.red
Color.self[keyPath: colorConstructor]
If we allow cases, we could even go a step further with static properties. Key paths to static properties will allow types to evolve from enums to structs without a source breakage. It would also be consistent with convenience static properties — e.g. static let 'default' = Self.black.
Finally, we could allow functions key paths, significantly improving @dynamicMemberLookup proxy types:
@dynamicMemberLookup
struct KeyPathIdentifiable<Root, Value: Hashable>: Identifiable
extension Identifiable {
static func identifiable(
_ root: Root, by keyPath: KeyPath<Root, Value>
) -> Identifying<Root, Value> where Self == Identifying<Root, Value>
}
// === Use ———————————————
struct User {
let id = UUID()
let name: String
func rename(to newName: String)
}
let user: some Identifiable = .identifiable(
User(name: "Sam"),
by: \.id
)
// ❌ Key paths cannot refer to functions
idUser.rename(to: "Liz")
Arguably, key paths to functions are a bit unrelated and pose problems on their own — i.e. "Can they be applied?", "How will the resulting key path be hashable?", "How can argument labels be carried?"