Casting a type to a Protocol with Self requirements

I want to access all the functionalities from Model in MyModel and in Model I want to cast a value Any to Model so that I can call a function implemented by Model. Maybe this is impossible...

if let modelValue = value as? Model {
 modelValue.getModel() 
}

Maybe I can have a generic constraint on the function? Which is Self? Is that possible?

This is confusing.

Here is a test snipped (I only wrote it down but never tested it, but it should work):

protocol Model {
  func getModel() -> Model
}

struct MyModel : Model {
  func getModel() -> Model {
    print("my model")
    return self
  }
}

let test: Any = MyModel()
if let model = test as? Model {
  model.getModel() // returns `Model` but also prints `"my model"` in this situation
}

It's not what you want?

Sorry - It is quite confusing to explain...

I want to return the Self type so when the user calls getModel() is gets back MyModel and not the type Model

So
MyModel().getModel() // Returns MyModel and not Model

I understand that you want that on functionality on the same type, but what is the cast for then? What are you trying to extract with the dynamic cast then?

myModel.getModel() will return again MyModel which is basically the same as just myModel.

I want the dynamic cast for recursion - I have a MyModel that could have a Model so I want to call that getModel() on the nested Model:

public protocol Model: Codable {
  func getModel() -> Self
}

extension Model {
  func getModel() -> Self {
    var values // Values of the Model as Dictionary -- [String: Any]
    if let modelValue = values[0] as? Model {
       _ = modelValue.getModel() // Throwing out the result
    }
    return self
  }
}

struct NestedModel: Model {
  let age: Int
}

struct MyModel: Model {
  let name: String
  let nestedModel: Model
}

Sorry I'm still confused by that. You cannot have a bare Model property due to Self requirement. I'd love to help but I'm having hard times understanding what you're building. You can help me by writing doing some 'wish' API and some result types with some comments on why you need those to be like you wish. However I'll reply a little bit later.

Maybe this example helps:

public protocol Model: Codable {
  func save(completion: (Self?, Error?) -> Void)
}

extension Model {
  func save(completion: (Self?, Error? -> Void) {
    var values = DictionaryEncoder(encode: self)
    for (key, value) in values {
      if let modelValue = value as? Model {
        modelValue.save { model, error in
           if let error = error {
              completion(nil, error)
              return
           }
            addForeignKey(to: values)
        }
      }
   } 

   let query = InsertQuery(from: values)

   // Execute INSERT statement in the database
   query.execute(using: connection)  { error
      completion(self, error)
   }
  }
}

struct NestedModel: Model {
  let age: Int
}

struct MyModel: Model {
  let name: String
  let nestedModel: Model
}

let nestedModel = NestedModel(age: 24)
let myModel = MyModel(name: "Enrique", nestedModel: nestedModel)

myModel.save { model,  error in // model is of type MyModel 
   // Do something
}

When saving a Model, I also want to save the nested Models