Generic parameter 'T' could not be inferred

Hi All,

Please consider the following example. I have two Entity classes both conforming to Model protocol. I'd like to take a certain action, which implementation depends on a specific entity type. For example, I'd like to JSON-encode the entity. For the sake of simplicity in this example I just print its type.

import Foundation
protocol Model {}

class Entity1 : Model {}
class Entity2 : Model {}
class Stub : Model {}

func getModelType<T: Model>(typeName: String) -> T.Type {
    switch typeName {
    case "e1":
        return Entity1.self as! T.Type
    case "e2":
        return Entity2.self as! T.Type
    default: return Stub.self as! T.Type
    }
}

let t = getModelType(typeName: "e1")
if t == Entity1.Type { print("Entity 1") }
else { print("Not Entity 1") }

I'm getting "Generic parameter 'T' could not be inferred" error in this line:
let t = getModelType(typeName: "e1")

Is there any workaround?

Thanks!

So your usage of generics in this function don't quite make sense because the caller can do something like:

let t: Stub.Type = getModelType(typeName: "e1")

which will result in a runtime failure. The reason you get the error that T couldn't be inferred is that there is no caller information on what this T type is, hence the reason one needs to add : SomeType.Type to the variable declaration. I believe you may want something like the following instead:

func getModelType(typeName: String) -> Model.Type { /* ... */ }

let t = getModelType(typeName: "e1")
if t == Entity1.self { /* ... */ }

where now we're returning some metatype whose base conforms to Model

Thanks for your comment, and your example certainly makes sense. Let's take it one step further. The Model is actually a Vapor Model protocol, and it comes with some restrictions. The issue now is
Protocol 'Model' can only be used as a generic constraint because it has Self or associated type requirements
I kinda understand the meaning, and this post explains is quite well... But how do I implement this seemingly simple and common pattern?

class Entity1 : Model {
    var id: String?
    typealias IDValue = String
}

class Entity2 : Model {
    var id: String?
    typealias IDValue = String
}

class Stub : Model {
    var id: String?
    typealias IDValue = String
}

func getModelType(typeName: String) -> Model.Type { // <<< New Error
    switch typeName {
    case "e1":
        return Entity1.self
    case "e2":
        return Entity2.self
    default: return Stub.self
    }
}

let t = getModelType(typeName: "e1")
if t == Entity1.self { print("Entity 1") }
else { print("Not Entity 1") }
Terms of Service

Privacy Policy

Cookie Policy