KeyPath.Value Type Conversion

Currently, the KeyPath types do not support type casting or generic containers for the Value type. For example, if I have a key-path \ which is they type KeyPath<Foo, Int>, I cannot assign it to KeyPath<Foo, Any> or using a type that Int conforms to, such as KeyPath<Foo, Hashable>.

My question is; is this how key-paths where designed? If so why, and if not, why does it not work?

Swift does not generally support covariance or contravariance in generic type parameters, and key paths would require both to support things like this in their current incarnation. Fully accurately capturing all the possible variance patterns in the type system today would furthermore be extremely complex due to the interactions with mutation; while a read-only key path could conceivably be handled as KeyPath<contravariant Root, covariant Value>, WritableKeyPaths would have to be invariant in both parameters, and ReferenceWritableKeyPath could only be contravariant in the Root parameter. Even if we could, this seems like it’d end up being a complex system hard for anyone to understand. If you want to work with a heterogeneous set of key paths, you can use PartialKeyPath<Foo> as a stand-in for read-only KeyPath<Foo, _>.

Possibly, in the fullness of time, I’d like to see us iterate on the design to make it based on protocols, which could let you express KeyPath where Root == Int, Value: Hashable as a set of constraints subsuming more specific constraints like Value == Int, Value == String, etc.