This is a case for type erasure, which usually can be done pretty easily with protocols.
You would define a new protocol called ViewModelProtocol (to avoid clashing with your existing ViewModel names in the example):
protocol ViewModelProtocol {
var joints: String { get }
init()
}
and then conform ViewModel2 to it with just:
extension ViewModel2: ViewModelProtocol { }
and then in your view controller:
class ViewController: UIViewController {
let model: ViewModelProtocol
func test() {
print("Joints \(model.joints)")
}
}
This is what's known as an "existential" protocol, and is currently only possible with protocols that do not have Self or associatedtype requirements, like your Joint protocol does.