在“PrimitiveSequence”上引用实例方法“xxx”需要类型“A”和“any B”等效

问题描述 投票:0回答:1

我们需要一些建议。我正在尝试做这样的抽象,所以我有很多不同的响应。在项目的某个时候,我们意识到我们的一些响应具有 id 属性,我们想为这些响应制定一些通用逻辑,而不用关心这个响应是什么。唯一重要的是那些 Responses 包含

id
字段。我们引入了
WithIdResponse
,并为包含
id
的响应创建了扩展,并且在已实现架构的上下文中很有用。

接下来我们为

Single
创建了 Reactive 虚拟扩展,它做简单的映射
WithIdResponse?
->
String?
我们称这个运算符为
id
.

现在 Swift 的问题是,当我们使用这个

id
运算符时,编译器会出现这样的错误:
Referencing instance method 'id()' on 'PrimitiveSequence' requires the types 'ItemAResponse' and 'any WithIdResponse' be equivalent

我们试图理解这条消息,但我们失败了。我们的假设在这里做错了什么吗?

import Foundation
import RxSwift

protocol WithIdResponse {
    var id: String { get }
}

extension PrimitiveSequence where Element == WithIdResponse?, Trait == SingleTrait {
    func id() -> Single<String?> {
        self.map { $0?.id }
    }
}

struct ItemAResponse {
    let id: String
}
extension ItemAResponse: WithIdResponse {}

struct ItemBResponse {
    let id: String
}
extension ItemBResponse: WithIdResponse {}

let subjectA: BehaviorSubject<ItemAResponse?> = BehaviorSubject(value: nil)
let subjectB: BehaviorSubject<ItemBResponse?> = BehaviorSubject(value: nil)

let singleA = subjectA.asSingle().id() // HERE WE HAVE ERROR
swift rx-swift swift-extensions
1个回答
0
投票

你要求元素是一个

Optional<any WithIdResponse>
。你需要你的通用类型来允许任何
WithIdResponse
.

的实现

这里是你如何做到的:

extension PrimitiveSequence where Trait == SingleTrait {
    func id<Wrapped>() -> Single<String?> where Element == Optional<Wrapped>, Wrapped: WithIdResponse {
        self.map { $0?.id }
    }
}

顺便说一句,你知道 Swift 库中已经有一个

Identifiable
类型吗?我建议你使用它而不是自己制作。

像这样的东西:

extension PrimitiveSequence where Trait == SingleTrait {
    func id<Wrapped>() -> Single<Wrapped.ID?> where Element == Optional<Wrapped>, Wrapped: Identifiable {
        self.map { $0?.id }
    }
}

struct ItemAResponse: Identifiable {
    let id: String
}

let subjectA: BehaviorSubject<ItemAResponse?> = BehaviorSubject(value: nil)

let singleA = subjectA.asSingle().id() // This is a `PrimitiveSequence<SingleTrait, String?>`
© www.soinside.com 2019 - 2024. All rights reserved.