Skip to content

WhenNotEmpty Method ​

The whenNotEmpty() method executes the given callback only when the collection has one or more items. This is useful for performing operations on collections that are guaranteed to have data.

Basic Syntax ​

typescript
collect(items).whenNotEmpty(callback: (collection: Collection<T>) => Collection<U>)

Examples ​

Basic Usage ​

typescript
import { collect } from 'ts-collect'

// Non-empty collection
const numbers = collect([1, 2, 3])
numbers.whenNotEmpty(collection =>
  collection.map(n => n * 2)
)
console.log(numbers.all()) // [2, 4, 6]

// Empty collection (callback not executed)
const empty = collect([])
empty.whenNotEmpty(collection =>
  collection.map(n => n * 2)
)
console.log(empty.all()) // []

Working with Objects ​

typescript
interface User {
  id: number
  name: string
  active: boolean
}

const users = collect<User>([
  { id: 1, name: 'John', active: true },
  { id: 2, name: 'Jane', active: false }
])

users.whenNotEmpty(collection =>
  collection.map(user => ({
    ...user,
    active: true
  }))
)

Real-world Examples ​

Data Processor ​

typescript
interface ProcessedData<T> {
  data: T
  processedAt: Date
  status: 'processed' | 'skipped'
}

class DataProcessor<T> {
  private items: Collection<T>

  constructor(items: T[]) {
    this.items = collect(items)
  }

  process(): ProcessedData<T>[] {
    return this.items
      .whenNotEmpty(collection =>
        collection.map(item => ({
          data: item,
          processedAt: new Date(),
          status: 'processed'
        }))
      )
      .all()
  }
}

// Usage
const processor = new DataProcessor([1, 2, 3])
const results = processor.process()

Analytics Aggregator ​

typescript
interface MetricData {
  timestamp: Date
  value: number
  category: string
}

class MetricsAggregator {
  private metrics: Collection<MetricData>

  constructor(metrics: MetricData[]) {
    this.metrics = collect(metrics)
  }

  calculateAverages() {
    return this.metrics.whenNotEmpty((collection) => {
      const categories = collection.pluck('category').unique()

      return categories.map(category => ({
        category,
        average: collection
          .filter(m => m.category === category)
          .average('value')
      }))
    })
  }
}

Advanced Usage ​

Report Generator ​

typescript
interface ReportData {
  id: string
  data: any
  timestamp: Date
}

interface Report {
  id: string
  summary: string
  details: any[]
  generatedAt: Date
}

class ReportGenerator {
  private data: Collection<ReportData>

  constructor(data: ReportData[]) {
    this.data = collect(data)
  }

  generateReport(): Report | null {
    return this.data
      .whenNotEmpty((collection) => {
        const processed = collection
          .sortBy('timestamp')
          .map(item => this.processItem(item))

        return collect([{
          id: `report-${Date.now()}`,
          summary: this.generateSummary(processed),
          details: processed.all(),
          generatedAt: new Date()
        }])
      })
      .first() || null
  }

  private processItem(item: ReportData) {
    // Processing logic
    return item
  }

  private generateSummary(data: Collection<ReportData>) {
    // Summary generation logic
    return `Report with ${data.count()} items`
  }
}

Batch Operation Handler ​

typescript
interface BatchOperation<T> {
  items: Collection<T>
  execute: () => Promise<T[]>
}

class BatchProcessor<T> implements BatchOperation<T> {
  items: Collection<T>

  constructor(items: T[]) {
    this.items = collect(items)
  }

  async execute(): Promise<T[]> {
    return this.items
      .whenNotEmpty(async (collection) => {
        console.log(`Processing ${collection.count()} items`)

        const processed = await Promise.all(
          collection.map(this.processItem)
        )

        return collect(processed)
      })
      .all()
  }

  private async processItem(item: T): Promise<T> {
    // Async processing logic
    return item
  }
}

Type Safety ​

typescript
interface TypedItem {
  id: number
  value: string
  metadata?: Record<string, any>
}

const items = collect<TypedItem>([
  { id: 1, value: 'one' },
  { id: 2, value: 'two' }
])

// Type-safe transformation
items.whenNotEmpty(collection =>
  collection.map(item => ({
    ...item,
    metadata: { processed: true }
  }))
)

// Type conversion
interface TransformedItem {
  originalId: number
  transformedValue: string
}

const transformed = items.whenNotEmpty(collection =>
  collection.map((item): TransformedItem => ({
    originalId: item.id,
    transformedValue: item.value.toUpperCase()
  }))
)

Return Value ​

  • Returns the result of the callback if the collection is not empty
  • Returns the original collection if empty
  • Maintains type safety with TypeScript through generics
  • Can change the type of the collection through the callback
  • Can be chained with other collection methods

Common Use Cases ​

  • Data transformation
  • Aggregation operations
  • Report generation
  • Batch processing
  • Conditional operations on non-empty collections

Released under the MIT License.