currently, i have a lot of database logic that’s built around String-backed CodingKey types. it is not a Codable-based system, but i understand Codable also has similar characteristics.
an example for the purposes of discussion:
struct Homeworld
{
var id:Int
var climate:String
}
extension Homeworld:BSONDecodable, BSONEncodable
{
enum CodingKey:String, Sendable
{
case id = "i"
case climate = "c"
}
}
struct Species
{
var id:Int
var portrait:Int
var name:String
var homeworld:Homeworld
var isSapient:Bool
var isEnslaved:Bool
}
extension Species:BSONDecodable, BSONEncodable
{
enum CodingKey:String, Sendable
{
case id = "_id"
case portrait = "p"
case name = "n"
case homeworld = "w"
case isSapient = "s"
case isEnslaved = "e"
}
}
this works well enough, but we’ve often introduced bugs in query builder logic that could have been prevented by better-typing the coding keys.
for example, when referencing a field of a nested document in the (MongoDB) query language, one must write a keypath such as '$w.i', which is analogous to \.homeworld.id in swift.
because the coding keys are stringly-typed, it is not possible to meaningfully type the keypath expressions:
let planet:Mongo.KeyPath = Species.CodingKey.homeworld
+ Homeworld.CodingKey.id
of course, it is easy to make a mistake without the guardrails of a strong type system. for example, you might forget to drill down to the nested id and return a keypath such as '$w', which has a pointee of type Homeworld and not Int.
it would be game-changing if we could specialize a keypath type to obtain something like:
let homeworld:Mongo.KeyPath<Species, Homeworld> = ...
let planet:Mongo.KeyPath<Homeworld, Int> = ...
return homeworld + planet // as Mongo.KeyPath<Species, Int>
but i have a hard time imagining how to set up something like this using features that currently exist in the language.