Swift: How to hold any possible instance of a generic type in a variable

The distillation of what I am trying to do is this:

public struct HolderOfWrappers
{
    let anyWrappedItem: MyResource<Any>
}

public struct MyResource<A>
{
    let wrappedItem : A
    let convert: String -> A
}

func holdResource<A>( resource: MyResource<A> ) -> HolderOfWrappers
{
    // Error on this line, A is not Any...
    let wrapHolder : HolderOfWrappers = HolderOfWrappers( resource )
    return wrapHolder
}

As it stands, this code produces the compiler error in the last holdResource method where I’m trying to build a HolderOfWrappers:

  • Popover doesn't center on button
  • Create an NSAlert with Swift
  • App Transport Security policy requires the use of a secure connection
  • How to decrement a Character that contains a digit?
  • Force Landscape when orientation is locked
  • NSPredicate with multiple arguments and “AND behaviour”
  • Cannot convert the expression's type 'MyResource<A>' to type '(anyWrappedItem: MyResource<Any>)'
    

    Which is understandable as the code indicates HolderOfWrappers can only hold a MyResource built for Any type, not any possible type. What I’m really after with the HolderOfWrappers is something like this:

    public struct HolderOfWrappers
    {
        let anyWrappedItem: MyResource<>
    }
    

    or even MyResource<*> – I am trying to say with this code that I’d like a variable that can hold any type of MyResource. If I try to use either syntax though, I get a compiler error that it expects a type.

    I could just have anyWrappedItem by of type Any, but then you lose the type information for future use. I also do not want HolderOfWrappers to be generic (because then I’d just have the same problem later).

    It’s almost like I am trying to treat the generic type as a protocol for the anyWrappedItem storage variable, which will not work for other reasons…

    2 Solutions Collect From Internet About “Swift: How to hold any possible instance of a generic type in a variable”

    I think you can do what you want by putting a generic parameter in your HolderOfWrappers init method. Basically, the init method just generates a new MyResource using the resource that you provide, like this:

    public struct HolderOfWrappers {
    
        let anyWrappedItem: MyResource<Any>
    
        public init<A>(resource: MyResource<A>) {
            self.anyWrappedItem = MyResource(wrappedItem: resource.wrappedItem, convert: resource.convert)
        }
    }
    

    I think that will do what you want. I don’t know if it will be slower since you are initializing an entirely new MyResource instead of just copying one.

    At any rate, it makes it so that HolderOfWrappers itself is not generic and will fill anyWrappedItem with a MyResource<Any> that holds the same values as the resource that you pass in.

    How about this

    protocol Wrapper {}
    
    public struct HolderOfWrappers {
        let anyWrappedItem: MyResource<Wrapper>
    }
    
    public struct MyResource<A> {
        let wrappedItem : A
        let convert: String -> A
    }
    
    func holdResource( resource: MyResource<Wrapper>) -> HolderOfWrappers {
        // Error on this line, A is not Any...
        let wrapHolder : HolderOfWrappers = HolderOfWrappers(anyWrappedItem: resource)
        return wrapHolder
    }
    

    of course the downside is you’d have to do extension A: Wrapper { } for any type A that you pass into MyResource.