Swift 基于泛型方法的快速型推理

Swift 基于泛型方法的快速型推理,swift,generics,type-inference,Swift,Generics,Type Inference,我正在开发一个SDK,并开发了一个非常简洁的组合管道方法,该方法接受一个用于解码json的通用参数。实际上,它是JSON->可解码的可重用组合管道。 效果非常好。下面是管道的外观: func records<Record: Decodable>(forRequest request:RestRequest ) -> AnyPublisher<[Record], Never> { return NetworkService.publisher(for: request

我正在开发一个SDK,并开发了一个非常简洁的组合管道方法,该方法接受一个用于解码json的通用参数。实际上,它是JSON->
可解码的可重用组合管道。
效果非常好。下面是管道的外观:

func records<Record: Decodable>(forRequest request:RestRequest ) -> AnyPublisher<[Record], Never> {
return NetworkService.publisher(for: request)
  .tryMap({ (response) -> Data in
    response.asData()
  })
  .decode(type: Wrapper<Record>.self, decoder: JSONDecoder())
  .map({ (record) -> [Record] in
    record.records
  })
  .catch({ _ in
    Just([Record]())
  })
  .eraseToAnyPublisher()
}
据我所知,Swift+Combine正在从
assign(to:,on:)
调用推断通用参数类型

但是超级强队需要一个非联合版本,我真的很难想出如何帮助斯威夫特推断出类型。我试着建立一个这样的直接模拟:

func fetchRecords<Record: Decodable>(forRequest request: RestRequest,
                   _ completionBlock: @escaping (Result<[Record], RestClientError>) -> Void) {

RestClient.shared.send(request: request) { result in
   switch result {
     case .success(let response):
       do {
          let decoder = JSONDecoder()
          let wrapper = try decoder.decode(Wrapper<Record>.self, from: response.asData())
          completionBlock(.success(wrapper.records))
       } catch {
          completionBlock(.success([Record]()))
       }
     case .failure(let err):
       completionBlock(.failure(err))
    }
  }
}
NetworkService.fetchRecords(forRequest: request) { records in
  print(records)
}
NetworkService.fetchRecords(ofType: ConcreteRecordType.self, forRequest: request) { result in
  // No need to specify closure argument type :) 

  switch result {
    case .success(let records):
       // "records" is of type [ConcreteRecordType]
       //...
    case .failure(let error):
       //...
  }
}
无法推断通用参数“Record”导致的极其隐秘的错误

在这个非合并版本中,我如何指定通用记录“类型”——任何符合可解码的记录

Ps:这是包装结构:

struct Wrapper<R: Decodable>: Decodable {
  var totalSize: Int
  var done: Bool
  var records: [R]
}
struct包装器:可解码{
var totalSize:Int
完成变量:Bool
var记录:[R]
}
您可以在闭包参数列表中指定泛型类型:

NetworkService.fetchRecords(forRequest: request) { (result: Result<[ConcreteRecordType], RestClientError>) { 
  switch result {
    case .success(let records):
       // "records" is of type [ConcreteRecordType]
       //...
    case .failure(let error):
       //...
  }
}
那么,你可以这样称呼它:

func fetchRecords<Record: Decodable>(forRequest request: RestRequest,
                   _ completionBlock: @escaping (Result<[Record], RestClientError>) -> Void) {

RestClient.shared.send(request: request) { result in
   switch result {
     case .success(let response):
       do {
          let decoder = JSONDecoder()
          let wrapper = try decoder.decode(Wrapper<Record>.self, from: response.asData())
          completionBlock(.success(wrapper.records))
       } catch {
          completionBlock(.success([Record]()))
       }
     case .failure(let err):
       completionBlock(.failure(err))
    }
  }
}
NetworkService.fetchRecords(forRequest: request) { records in
  print(records)
}
NetworkService.fetchRecords(ofType: ConcreteRecordType.self, forRequest: request) { result in
  // No need to specify closure argument type :) 

  switch result {
    case .success(let records):
       // "records" is of type [ConcreteRecordType]
       //...
    case .failure(let error):
       //...
  }
}

瞧!提供给
fetchRecords
的显式类型级联到闭包参数类型。无需在闭包参数列表中提供类型。

我的回答有用吗?请让我知道。@jacobRelkin-太完美了。谢谢