首页 > 解决方案 > 从其嵌套类型推断泛型类型

问题描述

我正在尝试创建一个Fetchable协议,该协议包含从中获取对象的位置作为其类型的一部分,而不是fetch使用显式类型参数编写函数,如下所示:

func fetch<Model: Fetchable>(_ type: Model.Type, path: Model.Path) -> AnyPublisher<[Model], Error> {
   print(path.value)
   // ...
}

我想ModelModel.Path参数中推断:

func fetch<Model: Fetchable>(path: Model.Path) -> AnyPublisher<[Model], Error> {
   print(path.value)
   // ...
}

这是由@RobNapier 的方法启发而来。它并不完全相同,因此我可能会遗漏重要的细节以使其发挥作用。

这是我所拥有的:

protocol Locatable {
   associatedtype Model
   var value: String { get }
}

protocol Fetchable: Codable {
   associatedtype Path: Locatable where Path.Model == Self
}

struct Message {
   let content: String
}

extension Message: Fetchable, Codable {
   enum Path: Locatable {
      typealias Model = Message
      case forUser(_ userId: String)
      var value: String {
         switch self {
         case .forUser(let userId): return "/user/\(userId)/messages"
         }
      }
   }
}

当我打电话时fetch,我得到一个错误"Generic parameter 'Model' could not be inferred"

let pub = fetch(path: Message.Path.forUser("123"))

但这适用于fetch明确接受类型参数的 a (甚至推断其自己的 Message.Path 类型):

let pub = fetch(Message.self, .forUser("123"))

知道如何(如果可能的话)解决这个问题吗?

标签: swift

解决方案


信息不足以推断,但如果我们写

let pub: AnyPublisher<[Message], Error> = fetch(path: Message.Path.forUser("123"))

一切顺利。

更新:嵌套类型只是一种不可分割的类型,因此为了帮助快速推断父级,我们需要反转声明,如下所示(使用 Xcode 12.1 测试):

func fetch<Path: Locatable>(path: Path) -> 
        AnyPublisher<[Path.Model], Error> where Path.Model: Fetchable {

现在你想要的表达成为可能

let pub = fetch(path: Message.Path.forUser("123"))

推荐阅读