What is flatMap vs map on Optional? What about Optional.map vs array map?

1.2.7 · L3 · Interview

Predict first

What is the type of a?

let s: String? = "42"
let a = s.map { Int($0) }
print(type(of: a))
  • Optional<Int>
  • Optional<Optional<Int>>
  • Int

Mental model. map wraps whatever you return in another box. flatMap refuses to double-box — it flattens one layer.

Optional.map transforms the wrapped value; the result is still optional. Returns T → result T?.

Optional.flatMap is for closures that already return an optional. It unwraps one extra layer, so U? stays U? instead of becoming U??.

On sequences the names differ: map is 1:1, compactMap drops nils, flatMap concatenates nested sequences. Optional.flatMap and Sequence.flatMap are different functions that happen to share a name.

Int($0) already returns Int?, and map wraps it again. flatMap flattens it back to Int?.

Common traps

  • Using map where the closure returns an optional. You get T?? and then need ?? or a second unwrap — a smell that flatMap was wanted.
  • Thinking compactMap and flatMap are interchangeable. flatMap on an array of arrays flattens; compactMap removes nils. Different jobs.

They might follow up with

  • Why was flatMap renamed to compactMap for optionals? Because overloading on “flattening” was ambiguous for sequences of optionals; compactMap made intent explicit.
  • What does try? f().map(g) do? Returns U?; if f throws you get nil, if it succeeds you map the value.

Related questions

  • 1.2.6 How does optional chaining (a?.b?.c) actually work?

← How does optional chaining (a?.b?.c) actually work?