Home > OS >  How can I map to a type in Combine?
How can I map to a type in Combine?

Time:10-20

I have numerous pages where users may input information. They may input the fields with dates, numbers, or text.

I am trying to receive all changes in Combine and get their outputs as Encodable so I can easily upload the results to the network.

A String is Encodable, so I thought this would be easy but I cannot get this to work in Combine. I get a compiler error:

Cannot convert return expression of type 'Publishers.Map<Published.Publisher, Encodable>' to return type 'Published.Publisher'

There is a workaround where I add another property in SampleTextHandler that is @Published var userTextEncodable: Encodable but that's not what I want to do.

import Combine

protocol FieldResponseModifying {
    var id: String { get }
    var output: Published<Encodable>.Publisher { get }
}


struct SampleTextWrapper {
    var output: Published<Encodable>.Publisher {
        // Cannot convert return expression of type 'Publishers.Map<Published<String>.Publisher, Encodable>' to return type 'Published<Encodable>.Publisher'
        handler.$userTextOutput.map { $0 as Encodable}
    }
    
    let id = UUID().uuidString
    let handler = SampleTextHandler()
}

class SampleTextHandler {
   @Published var userTextOutput = ""
    init () { }
}

CodePudding user response:

Combine uses generics heavily. For example, the type returned by your use of map is Publishers.Map<Published<Value>.Publisher, Encodable>. So you could declare your property like this:

var output: Publishers.Map<Published<Encodable>.Publisher, Encodable> {
    handler.$userTextOutput.map { $0 as Encodable}
}

But now your property's type depends closely on how it is implemented. If you change the implementation, you'll have to change the type.

Instead, you should almost certainly use the “type eraser” AnyPublisher, like this:

var output: AnyPublisher<Encodable, Never> {
    handler.$userTextOutput
        .map { $0 as Encodable }
        .eraseToAnyPublisher()
}

You're probably going to run into another issue down the line, due to your use of the Encodable existential. When you hit that, you'll want to post another question.

  • Related