Skip to content
Back to skills

1150 Operators 0f7d099e

ASecurity

| Operator | Purpose | |----------|---------| | `map` | Transform each value 1:1 | | `tryMap` | Transform with throwing closure (erases error type) | | `flatMap` | Transform to new publisher, flatten nested publishers | | `compactMap` | Transform and filter out nil values | | `scan` | Accumulate values over time (emits each step) |

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmentgoswiftreactapi

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1150-operators_0f7d099e --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1150 Operators 0f7d099e?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1150 Operators 0f7d099e
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1150-operators-0f7d099e/badge)](https://www.skillsdirectory.com/skills/tools-only-1150-operators-0f7d099e)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Combine Operators

## Key Operators by Category

### Transforming
| Operator | Purpose |
|----------|---------|
| `map` | Transform each value 1:1 |
| `tryMap` | Transform with throwing closure (erases error type) |
| `flatMap` | Transform to new publisher, flatten nested publishers |
| `compactMap` | Transform and filter out nil values |
| `scan` | Accumulate values over time (emits each step) |

### Combining
| Operator | Purpose |
|----------|---------|
| `merge` | Interleave values from publishers of same type |
| `combineLatest` | Emit tuple of latest values when any emits |
| `zip` | Pair values by index (waits for all to emit) |
| `switchToLatest` | Switch to latest inner publisher, cancel previous |

### Timing
| Operator | Purpose |
|----------|---------|
| `debounce` | Wait for pause in emissions |
| `throttle` | Limit rate of emissions |
| `delay` | Shift emissions forward in time |
| `timeout` | Fail if no value within time limit |

## map vs flatMap vs switchToLatest

| Scenario | Use |
|----------|-----|
| Transform value: `String` → `Int` | `map` |
| Transform to publisher: `URL` → `Publisher<Data>` | `flatMap` |
| Transform to publisher, cancel previous | `map` + `switchToLatest` |

```swift
// map: Simple transformation
publisher.map { $0.uppercased() }

// flatMap: Transformation produces a publisher
publisher.flatMap { url in
    URLSession.shared.dataTaskPublisher(for: url)
}

// switchToLatest: Cancel previous (search/autocomplete)
searchText
    .map { query in searchAPI(query) }
    .switchToLatest()  // Cancels previous request
```

## combineLatest vs merge vs zip

| Aspect | merge | combineLatest | zip |
|--------|-------|---------------|-----|
| **Output** | Same type | Tuple | Tuple |
| **Emits when** | Any emits | Any (after all emit once) | All emit new value |
| **Use for** | Multiple event sources | Form validation | Parallel requests |

```swift
// merge: Combine same-type streams
let allTaps = buttonA.merge(with: buttonB)

// combineLatest: React to any change (form validation)
Publishers.CombineLatest(emailValid, passwordValid)
    .map { $0 && $1 }

// zip: Wait for both (parallel requests)
Publishers.Zip(fetchUser, fetchPreferences)
```

## Critical Anti-Patterns

### 1. flatMap Instead of switchToLatest for Search

```swift
// BAD: All requests execute, results arrive out of order
searchText.flatMap { query in search(query) }

// GOOD: Cancel previous requests
searchText
    .map { query in search(query) }
    .switchToLatest()
```

### 2. Wrong Threading Operator

```swift
// BAD: subscribe(on:) doesn't affect where values received
URLSession.shared.dataTaskPublisher(for: url)
    .subscribe(on: DispatchQueue.main)  // WRONG!
    .sink { /* NOT on main thread */ }

// GOOD: Use receive(on:) for downstream
URLSession.shared.dataTaskPublisher(for: url)
    .receive(on: DispatchQueue.main)
    .sink { /* On main thread */ }
```

### 3. combineLatest with Publisher That Never Emits

```swift
// BUG: Won't emit until ALL publishers emit at least once
Publishers.CombineLatest(requiredField, optionalAction)
// If optionalAction never fires, stream never starts
```

### 4. Using tryMap Without mapError

```swift
// BAD: Erases error type to plain Error
publisher.tryMap { try decode($0) }

// GOOD: Restore specific error type
publisher.tryMap { try decode($0) }
    .mapError { $0 as? APIError ?? .unknown($0) }
```

## Review Questions

1. Is `flatMap` appropriate, or should it be `map + switchToLatest`?
2. Are `combineLatest` publishers guaranteed to emit at least once?
3. Is `receive(on:)` used before UI updates (not `subscribe(on:)`)?
4. Are try* operators followed by `mapError` for type safety?
5. Could `debounce` or `throttle` reduce unnecessary work?

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.