使用保护语句解包泛型函数时无法推断出泛型参数 'T'

Generic parameter 'T' could not be inferred when using a guard statement to unwrap a generic function

我试图在 Combine 中使用通用模块化函数,但我收到无法推断通用的错误。

func foo<T>(data: T) -> AnyPublisher<Bool, MyError> {
    
}

func bar<T>(data: T) -> AnyPublisher<String, MyError> {
    Deferred { [weak self] () -> AnyPublisher<Bool, MyError> in
        guard let foo = self?.foo else { // error here
            return Fail(error: .someError)
                .eraseToAnyPublisher()
        }
        
        return foo(data)
    }
    .eraseToAnyPublisher()
    .flatMap { [weak self] (value) -> AnyPublisher<String, MyError> in
        Future<String, MyError> { [weak self] promise in
            // do something with the returned value 
            promise(.success("Success"))
        }
        .eraseToAnyPublisher()
    }
    .eraseToAnyPublisher()
}

enum MyError: Error {
    case someError
}

我在尝试使用 guard 语句解包函数时遇到错误。 T 没有约束,因为它可能是多种不同的类型,例如 DataUIImage,它们在 foo 函数中进行类型检查。

当您遇到这样的问题时,简化。我们可以将现象简化为一个非常简单的案例:

class MyClass {
    func foo<T>(data: T) -> Void { }
    func bar<T>(data: T) -> Void {
        let foo = self.foo // error
    }
}

现在,首先要意识到您有两个单独的 T 占位符。你说 foobar 是 T,但它们之间没有关系。我们可以改写得更清楚:

class MyClass {
    func foo<FooDataType>(data: FooDataType) -> Void { }
    func bar<BarDataType>(data: BarDataType) -> Void {
        let foo = self.foo // error: Generic parameter 'FooDataType' could not be inferred
    }
}

现在很清楚问题出在哪里,因为我们知道哪个 占位符是编译器遇到的问题。当您这样看时,您会意识到 FooDataType 完全局限于 foobar 怎么知道这将是什么类型?

如果您的想法是它们应该是相同的 类型,那就这么说吧。使 class 成为通用函数,而不是单个函数:

class MyClass<T> {
    func foo(data: T) -> Void { }
    func bar(data: T) -> Void {
        let foo = self.foo // fine
    }
}