Associated types and primary associated types

Swift language Senior Swift 5.7+ iOS 17+ Reviewed By Alok Singh

Pick the fix

You need a function that saves a User to any store whose Item is User. Which signature?

protocol Store<Item> {
    associatedtype Item
    func save(_ item: Item) throws
}
Options
Hint 1 of 1

How do you say 'a Store of Users'?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A func persist(_ u: User, in store: some Store<User>) with protocol Store<Item>

Correct. The primary associated type pins Item to User.

Why not the others?
  • B func persist(_ u: User, in store: any Store). Item is unknown, so store.save(u) won't type-check.
  • C Cast with store.save(u as! Store.Item). You can't name the associated type like that, and force casts crash.
  • D Declare associatedtype Item = Any. That throws away type safety for every conformer.

30-second answer

An associated type is a placeholder a conforming type fills in, like Element in Collection. It makes the protocol generic. Since Swift 5.7, primary associated types (protocol Store<Item>) let you write constraints like some Store<User> or any Store<User> without verbose where clauses.

Practise saying it · 30 s. No recording, just a timer

Explain associated types.

Say your answer out loud, then check which of these points you covered:

  • Placeholder filled by conformers
  • Primary associated types
  • Existentials hide the type

Deep dive

Protocols with associated types can be used as any P, but you lose access to members that use the associated type unless it is constrained.

Conforming types often infer the associated type from method signatures.

Constrain associated types: associatedtype Item: Codable.

Type erasure wrappers (AnyPublisher) predate any P<T>.

Common mistakes

  • Making the associated type Any to avoid generics.
  • Force-casting to the associated type.

Senior take & follow-ups

Seniors use primary associated types and understand what an existential hides.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why can't you call save(_:) on a plain any Store?

    Show hint

    The Item type is unknown.

  2. When do you still write a type-erasing wrapper?

    Show hint

    When you need behaviour that any P<T> doesn't give, or older OS support.

Suggest a fix if something here is wrong or out of date.