Skip to content

SkipWhile Method ​

The skipWhile() method skips items in the collection while the given callback returns true and returns the remaining items. Unlike skipUntil(), it stops skipping when the condition becomes false.

Basic Syntax ​

typescript
collect(items).skipWhile((item: T) => boolean)

Examples ​

Basic Usage ​

typescript
import { collect } from 'ts-collect'

// Skip while numbers are less than 3
const numbers = collect([1, 2, 3, 4, 2, 1])
console.log(numbers.skipWhile(num => num < 3).all())
// [3, 4, 2, 1]

// Skip while strings start with 'a'
const words = collect(['apple', 'apricot', 'banana', 'apple', 'cherry'])
console.log(words.skipWhile(word => word.startsWith('a')).all())
// ['banana', 'apple', 'cherry']

Working with Objects ​

typescript
interface Task {
  id: number
  status: 'completed' | 'pending' | 'failed'
  priority: number
}

const tasks = collect<Task>([
  { id: 1, status: 'completed', priority: 1 },
  { id: 2, status: 'completed', priority: 2 },
  { id: 3, status: 'pending', priority: 3 },
  { id: 4, status: 'completed', priority: 4 }
])

// Skip while tasks are completed
const incompleteTasks = tasks.skipWhile(task => task.status === 'completed')
console.log(incompleteTasks.all())
// [
//   { id: 3, status: 'pending', priority: 3 },
//   { id: 4, status: 'completed', priority: 4 }
// ]

Real-world Examples ​

Log Analysis ​

typescript
interface LogEntry {
  timestamp: Date
  level: 'debug' | 'info' | 'warning' | 'error'
  message: string
  metadata?: Record<string, any>
}

class LogAnalyzer {
  private logs: Collection<LogEntry>

  constructor(logs: LogEntry[]) {
    this.logs = collect(logs)
  }

  getLogsAfterDebug(): LogEntry[] {
    // Skip while logs are debug level
    return this.logs
      .skipWhile(log => log.level === 'debug')
      .all()
  }

  getLogsAfterQuietPeriod(threshold: number): LogEntry[] {
    let lastTimestamp: Date | null = null

    return this.logs
      .skipWhile((log) => {
        if (!lastTimestamp) {
          lastTimestamp = log.timestamp
          return true
        }

        const timeDiff = log.timestamp.getTime() - lastTimestamp.getTime()
        lastTimestamp = log.timestamp
        return timeDiff < threshold
      })
      .all()
  }
}

Transaction Processing ​

typescript
interface Transaction {
  id: string
  amount: number
  status: 'pending' | 'processing' | 'completed' | 'failed'
  timestamp: Date
  retryCount: number
}

class TransactionProcessor {
  private transactions: Collection<Transaction>

  constructor(transactions: Transaction[]) {
    this.transactions = collect(transactions)
  }

  getTransactionsAfterFailures() {
    return this.transactions
      .skipWhile(tx => tx.status === 'failed')
      .map(tx => this.processTransaction(tx))
      .all()
  }

  getTransactionsAfterRetries() {
    return this.transactions
      .skipWhile(tx => tx.retryCount > 0)
      .all()
  }

  private processTransaction(tx: Transaction): Transaction {
    // Processing logic...
    return {
      ...tx,
      status: 'processing'
    }
  }
}

Advanced Usage ​

Data Stream Processing ​

typescript
interface DataPacket {
  sequence: number
  payload: string
  corrupted: boolean
  metadata: {
    timestamp: Date
    source: string
  }
}

class StreamProcessor {
  private packets: Collection<DataPacket>

  constructor(packets: DataPacket[]) {
    this.packets = collect(packets)
  }

  processAfterCorruption() {
    return this.packets
      .skipWhile(packet => packet.corrupted)
      .map(this.processPacket)
      .all()
  }

  processAfterSource(source: string) {
    return this.packets
      .skipWhile(packet => packet.metadata.source === source)
      .map(this.processPacket)
      .all()
  }

  private processPacket(packet: DataPacket) {
    return {
      ...packet,
      processed: true,
      payload: packet.payload.toUpperCase()
    }
  }
}

Time Series Analysis ​

typescript
interface TimeSeriesData {
  timestamp: Date
  value: number
  confidence: number
}

class TimeSeriesAnalyzer {
  private data: Collection<TimeSeriesData>

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

  getDataAfterStability(confidenceThreshold: number) {
    return this.data
      .skipWhile(point => point.confidence < confidenceThreshold)
      .all()
  }

  getDataAfterThreshold(valueThreshold: number) {
    let consecutive = 0
    const requiredCount = 3

    return this.data
      .skipWhile((point) => {
        if (point.value > valueThreshold) {
          consecutive++
        }
        else {
          consecutive = 0
        }
        return consecutive < requiredCount
      })
      .all()
  }
}

Type Safety ​

typescript
interface TypedItem {
  id: number
  value: number
  status: 'active' | 'inactive'
  metadata?: {
    tags: string[]
    priority: number
  }
}

const items = collect<TypedItem>([
  { id: 1, value: 10, status: 'inactive' },
  { id: 2, value: 20, status: 'inactive' },
  { id: 3, value: 30, status: 'active' },
  { id: 4, value: 40, status: 'active' }
])

// Type-safe callback
const activeItems = items.skipWhile((item: TypedItem) => {
  return item.status === 'inactive' // TypeScript validates status values
})

// Complex type-safe conditions
const highPriorityItems = items.skipWhile((item) => {
  return !item.metadata || item.metadata.priority < 5
})

Return Value ​

  • Returns a new Collection instance containing items after the condition becomes false
  • Returns empty collection if condition never becomes false
  • Original collection remains unchanged
  • Maintains type safety with TypeScript
  • Can be chained with other collection methods

Released under the MIT License.