When NOT to use eraseToAnyPublisher()

Viewed 1690

Combine seems to be built with type-erasure in mind. One reason is to avoid the complex types that are generated by many chained operators, such as the explanation defined in this question.

I'm curious about the cases where you would not want to call eraseToAnyPublisher(). I thought of a possible candidate:

func fetchResource() -> Future<Model, Error>

In this case, fetchResource isn't meant to emit more than once, and giving the return type of Future would add clarity to the functionality.

You could also return AnyPublisher:

func fetchResource() -> AnyPublisher<Model, Error>

This allows you to hide the implementation details from the consumer and protect against misuse. There is a tradeoff though... the consumer wouldn't know the semantics of the Future:

  • Future executes as soon as it's created, compared to some publishers that emit values only when there's a subscription
  • Future retains their eventual result and shares/replays the value to any future subscribers

Anyone know of any good examples of when you wouldn't eraseToAnyPublisher()?

1 Answers
  1. AnyPublisher is only a temporary solution until we're able to add constraints to opaque types.

e.g. this…

var publisher: AnyPublisher<Int, Never> { .init(Just(1)) }

…should actually be something like this:

var publisher<Publisher: Combine.Publisher>: some Publisher
where Publisher.Output == Int, Publisher.Failure == Never {
  Just(1)
}

You'll find a lot of discussion on the Swift forum about how this is not easy to implement (and what syntax to use!), hence why we're still using the intermediate solution of public type-erasing types.


  1. There's no protocol in between Future and Publisher. That's what you're looking for, with this question. If you'd like to enforce a stronger contract, add some stuff to an inherited protocol…
protocol Futurey: Publisher {
extension Future: Futurey {

…and then, unfortunately, you'll have to create another erasing type. For now.

struct AnyFuturey<Output, Failure> {
Related