CodingKey.Type with protocol and generic?

I have an error due to my usage of protocols and generic that I don't understand. Any help appreciated.

Context:

I'm writing code to decode a JSON doc whose format can differ based on a version field.

Example

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": ...,

or

  "$schema": "http://json-schema.org/2020_12/schema#",
  "$defs": ...,

I wrote a protocol and two struct to support the two dialects.

protocol JSONSchemaDialect {
    func codingKeys() -> CodingKey.Type
}

struct JSONSchemaDialect_2020_12: JSONSchemaDialect {
    // standard coding keys
    enum CodingKeys: String, CodingKey {
        case description = "$defs"
    }
    func codingKeys() -> CodingKey.Type {
        return CodingKeys.self
    }
}
typealias JSONSchemaDialect_2019_09 = JSONSchemaDialect_2020_12

struct JSONSchemaDialect_Draft4: JSONSchemaDialect {

    // Draft4 coding keys
    enum CodingKeys: String, CodingKey {
        case description = "definitions"
    }
    func codingKeys() -> CodingKey.Type {
        return CodingKeys.self
    }
}

and then I have a generic function to decode either schema.

    private func decodeDescription<T: JSONSchemaDialect>(from decoder: any Decoder, for dialect: T) throws -> [String: JSONUnionType] {

        // Cannot convert value of type 'any CodingKey.Type' to expected argument type 'Key.Type'
        // Generic parameter 'Key' could not be inferred
        let container = try decoder.container(keyedBy: dialect.codingKeys())

        return try container.decodeIfPresent([String: JSONUnionType].self, forKey: .definitions)
    }

How can I implement this in a generic way ?

Here is a partial solution. Using associatedtype allows me to go one step further. But I'm still blocked. The error is
Type 'T.CodingKeys' has no member 'definitions'

protocol JSONSchemaDialect {
    associatedtype CodingKeys: CodingKey
    init()
    func codingKeys() -> CodingKeys.Type
}

struct JSONSchemaDialect_2020_12: JSONSchemaDialect {
    // standard coding keys
    enum CodingKeys: String, CodingKey {
        case definitions = "$defs"
    }
    func codingKeys() -> CodingKeys.Type {
        return CodingKeys.self
    }
}

struct JSONSchemaDialect_Draft4: JSONSchemaDialect {
    // Draft4 coding keys
    enum CodingKeys: String, CodingKey {
        case definitions = "definitions"
    }
    func codingKeys() -> CodingKeys.Type {
        return CodingKeys.self
    }
}

and here is how I use this is a generic struct

        let dialect: T = .init()
        let container = try decoder.container(keyedBy: dialect.codingKeys()) // Works now !

        // compiler error : Type 'T.CodingKeys' has no member 'definitions'
        self.definitions = try container.decodeIfPresent([String: JSONUnionType].self, forKey: .definitions)