Custom AnyXYZ with implicit casting (like AnyHashable)

Has anyone explored implementing a custom AnyXYZ wrapper that works like AnyHashable?

For example, if I want to have a AnyHashableCodable wrapper that has similar syntactical sugar so I could do the following:

var dictionary: Dictionary<AnyHashableCodable, AnyHashableCodable > = [:]
dictionary["myKey"] = 2
let value: Int? = dictionary["myKey"] as? Int

The main place where I am finding myself wanting this is when working with Dictionary and Set.

Right now it seems I either have to allow a user to send any hashable value in as a key (and then deal with typecasting to the right protocol) or create a struct wrapper that then removes all the niceties that AnyHashable enables.

I took a look at stdlib and tried an initial attempt using cxx interop but my knowledge/experience with c++ is medium-low.

I don't quite understand the desired behaviour. E.g. what do you want to happen here:

var dictionary: Dictionary<AnyHashableCodable, AnyHashableCodable > = [:]
dictionary["myKey"] = 2
let value: String = dictionary["myKey"] // ?

Sorry about that, my example wasn't quite right. I updated my original post to:

var dictionary: Dictionary<AnyHashableCodable, AnyHashableCodable > = [:]
dictionary["myKey"] = 2
let value: Int? = dictionary["myKey"] as? Int

I think TLDR is I want something that has the same usability as AnyHashable but can be further restricted to other protocols. Ideally I could just do:

var dictionary: Dictionary<any Hashable & Codeable, any Hashable & Codeable > = [:]

But I understand why that is complicated / not currently possible.

If you were to implement an AnyHashableCodable type, how would you decode a value from JSON?

The same way you'd do with any Decodable or any Encodable:

if let encodable = dictionary["myKey"] {
  let data: Data = try JSONEncoder().encode(encodable)
}

That’s how you’d encode. But how would you know which type of value to decode?

I mean, I think that is an issue with any type of type erasure. I tried to use this example because it felt straightforward but understand your point.

In general the times I want to do this is when I've created a protocol that has x types that conform to it, and I want to use that protocol type as a key in a dictionary or in a set.

So I don't think this is specific to Codable, and I don't think what I am proposing creates new issues that are not already present with any type erasure.

That makes a lot of sense. Sorry for the distraction here!

There isn’t a way to implement implicit casts like there are for AnyHashable with your own types. I would argue that this is a benefit since there are a fixed number of implicit casts that you need to learn and then you can use that information to understand any Swift code, but it can definitely be very annoying in cases like these.

1 Like

No problem, appreciate the engagement!