Part of the point of opaque type is that there isn’t a representation in terms of other types. In the example of SPIR-V image types, presumably a concrete underlying hardware implementation has some underlying type, but the SPIR-V backend as I understand it potentially targets vendor-agnostic SPIR-V.
One thing that occurred to me is that ScalableVectorTypes (e.g. <vscale x i32>) don’t have a size but can be used with alloca, load, store. Given that, perhaps having opaque types without a default size isn’t too onerous after all?