The crucial step seems to be in making the wrapper parameter a virtual interface and then using that "as is" within the wrapper (rather than passing simple parameter types and using them to define a virtual interface within the wrapper). e.g.
Yes, without the virtual keyword an interface name is not a type. It is in the same category of not-type, not-variable 'something else' that modules, modports, clocking blocks and interfaces fall in.
That is one of my big hates toward SV, there are too many *different* things. IMHO, modules, interfaces, clocking block/etc/etc all should have been rationalized into an object model, instead of keeping them as a separate 'magic' concept. Modern high level language design has been moving in a direction that magic concepts are bad for a long time.
As we've seen in several threads lately, trying to mix the structure world of interfaces and modules with the dynamic class world is a huge PITA in anything but the most simple of cases.
Unfortunately, the SystemVerilog preprocessor (svpp) in IUS (6.20-s005) doesn't seem to be able to cope with a virtual interface parameter so this approach can only be used at present with Questa :(
This reminds me a lot of the early C++ days where compiler writers tried hard to not make a full meta-programming environment in the compiler and it never worked right. It took a long time before C++ compilers were actually expanding and evaluating template code with the full generality of the language. As you observed even things that should work in Questa do not. I've found numerous cases where something that should be statically evaluated based the template parameter does not work, ie something like:
bit [$size(ifi.foo)-1:0] bar;
Bails even though it is statically defined.
At least for C++ the preprocessor approach to templates ended up being doomed as it was never able to fully cope with the generality. The pre-processor would have been as complex as the compiler front end.