Ok, I'll try to explain you what I'm trying to get with a minimum viable example: I'd like to have a struct like this:
struct MyStruct {
let aBool: Bool
let aInt: Int
let aHashable: Hashable?
}
but of course this can't be done because:
Protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements
and this is fine. I can get what I want this way:
struct MyStruct<T> where T: Hashable {
let aBool: Bool
let aInt: Int
let aHashable: T?
}
But I want my struct to have two init this way:
struct MyStruct<T> where T: Hashable {
let aBool: Bool
let aInt: Int
let aHashable: T?
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
init(aHashable: T?) {
self.init(aBool: false, aInt: 0, aHashable: aHashable)
}
private init(aBool: Bool, aInt: Int, aHashable: T?) {
self.aBool = aBool
self.aInt = aInt
self.aHashable = aHashable
}
}
And if I try to init the struct like this:
let myStruct = MyStruct(aBool: true, aInt: 10)
I get an error:
Generic parameter 'T' could not be inferred
The problem is that even if I turn the struct into a non generic struct (with a couple of generic init):
struct MyStruct {
let aBool: Bool
let aInt: Int
let aHashable: T?
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
init<T>(aHashable: T?) where T: Hashable {
self.init(aBool: false, aInt: 0, aHashable: aHashable)
}
private init<T>(aBool: Bool, aInt: Int, aHashable: T?) where T: Hashable {
self.aBool = aBool
self.aInt = aInt
self.aHashable = aHashable
}
}
I still get an error. This time on the let aHashable: T? stored property:
Use of undeclared type 'T'
What's the right way to get what I want? Thank you.
MyStruct<Something>(aBool: true, aInt: 10). Depending on how you're actually using this object it might work for you to keep it not generic and useAnyHashable?as the type for your property - danMyStruct<Something>(aBool: true, aInt: 10). It's really weird to force the user of this "api" to specify a random type that conforms to Hashable just to silence the problem. AnyHashable might be a solution, but I guess it could be a solution that doesn't involve type erasure. If I'm not wrong I've already seen some API from Apple doing the same. - matteopucfalse/0a valid substitute for a hashable thing? There's a lot of important back story here. - Alexanderinit. For example:init(destinationName: String, isActive: Binding<Bool>, @ViewBuilder label: () -> Label)andinit<V>(destination: Destination, tag: V, selection: Binding<V?>, @ViewBuilder label: () -> Label) where V : HashableThe second one is generic, but the main Struct (NavigationLink) is not. - matteopucNavigationLinkisn't exactly relevant, because it doesn't store a value of a generic type (as is the case here withaHashable: T). There's nothing special about a non-generic type having a generic func/init, and that's just whatNavigationLInkis. - Alexander