What is a type eraser (AnyHashable, AnyView, AnyCancellable)? When do you write one?

1.3.7 · L3 · Interview

Predict first

What does this print?

let a: AnyHashable = 1
let b: AnyHashable = "1"
print(a == b)
  • true
  • false
  • Compile error

Mental model. A type eraser is a plain brown envelope: it hides what is inside so a shelf can hold envelopes of many different contents.

A type eraser is a concrete wrapper that hides a generic or associated type behind a uniform surface: AnyHashable, AnyView, AnyPublisher, AnyCancellable, AnySequence.

You write one when a public API cannot leak some/generics — most commonly to store heterogeneous conformers in one property or array. Prefer any P or primary associated types when they suffice; hand-written erasers are maintenance and add a layer of indirection.

The eraser keeps the underlying type. An Int and a String are never equal, even inside the same box.

Common traps

  • Writing an eraser for every PAT. Modern Swift can often express the same thing with any P<T> — check before adding a type.
  • Erasing too early. AnyView in SwiftUI loses identity and can force re-renders; erase only at the boundary that needs it.

They might follow up with

  • How does AnyCancellable erase anything? It wraps Cancellable so a set can hold subscriptions of any publisher type and cancel them on deinit.
  • What is the cost? An extra allocation and an indirect call per operation, plus lost specialization.

Related questions

  • 1.3.5 What is an associated type? Why can’t you write let x: MyPAT easily?
  • 1.3.6 What is a primary associated type? Give an example.
  • 1.4.2 some View vs any View — what is the difference, and why does SwiftUI use some?

← What is a primary associated type? Give an example.   How do you evolve a public protocol without breaking clients? →