whereNotNull Method
The whereNotNull() method filters the collection to include only items where the specified key's value is not null or undefined. This is particularly useful for finding complete records and validating data presence.
Basic Syntax
typescript
collect(items).whereNotNull(key: keyof T): Collection<T>Examples
Basic Usage
typescript
import { collect } from 'ts-collect'
// Simple not-null check
const items = collect([
{ id: 1, name: 'Widget', description: null },
{ id: 2, name: 'Gadget', description: 'A cool gadget' },
{ id: 3, name: 'Tool', description: null }
])
const withDescriptions = items.whereNotNull('description')
console.log(withDescriptions.all())
// [
// { id: 2, name: 'Gadget', description: 'A cool gadget' }
// ]Working with Objects
typescript
interface Product {
id: number
name: string
price: number | null
inStock: boolean | null
lastSold: Date | null
}
const products = collect<Product>([
{ id: 1, name: 'Widget', price: 99.99, inStock: true, lastSold: new Date() },
{ id: 2, name: 'Gadget', price: null, inStock: true, lastSold: null },
{ id: 3, name: 'Tool', price: 49.99, inStock: null, lastSold: new Date() }
])
// Find products with prices
const pricedProducts = products.whereNotNull('price')
// Find products with known stock status
const stockKnown = products.whereNotNull('inStock')
// Find products with sales history
const withSales = products.whereNotNull('lastSold')Real-world Examples
Product Listing Manager
typescript
interface ListingData {
sku: string
name: string
description: string | null
price: number | null
images: string[] | null
specifications: Record<string, string> | null
}
class ListingManager {
constructor(private listings: Collection<ListingData>) {}
getPublishableListings(): Collection<ListingData> {
return this.listings
.whereNotNull('description')
.whereNotNull('price')
.whereNotNull('images')
.whereNotNull('specifications')
}
getListingStatus(): {
total: number,
publishable: number,
requiresWork: Collection<ListingData>
} {
const publishable = this.getPublishableListings()
return {
total: this.listings.count(),
publishable: publishable.count(),
requiresWork: this.listings
.filter(listing => !publishable.pluck('sku').contains(listing.sku))
}
}
getCompletionReport(): Record<string, number> {
return {
description: this.listings.whereNotNull('description').count(),
price: this.listings.whereNotNull('price').count(),
images: this.listings.whereNotNull('images').count(),
specifications: this.listings.whereNotNull('specifications').count()
}
}
}Order Tracking System
typescript
interface OrderStatus {
orderId: string
processedAt: Date | null
shippedAt: Date | null
deliveredAt: Date | null
trackingNumber: string | null
estimatedDelivery: Date | null
}
class OrderTracker {
constructor(private orders: Collection<OrderStatus>) {}
getActiveShipments(): Collection<OrderStatus> {
return this.orders
.whereNotNull('shippedAt')
.whereNotNull('trackingNumber')
.whereNull('deliveredAt')
}
getTrackableOrders(): Collection<OrderStatus> {
return this.orders
.whereNotNull('trackingNumber')
.whereNotNull('estimatedDelivery')
}
getShipmentProgress(): Record<string, number> {
const total = this.orders.count()
return {
processed: this.orders.whereNotNull('processedAt').count() / total * 100,
shipped: this.orders.whereNotNull('shippedAt').count() / total * 100,
delivered: this.orders.whereNotNull('deliveredAt').count() / total * 100
}
}
}Advanced Usage
Customer Analysis System
typescript
interface CustomerData {
id: string
email: string
phoneNumber: string | null
preferences: string[] | null
lastPurchase: Date | null
segment: string | null
}
class CustomerAnalyzer {
constructor(private customers: Collection<CustomerData>) {}
getMarketableCustomers(): {
email: Collection<CustomerData>,
phone: Collection<CustomerData>,
both: Collection<CustomerData>
} {
const withEmail = this.customers.whereNotNull('email')
const withPhone = this.customers.whereNotNull('phoneNumber')
return {
email: withEmail,
phone: withPhone,
both: withEmail.intersect(withPhone)
}
}
getSegmentedCustomers(): Collection<CustomerData> {
return this.customers
.whereNotNull('segment')
.whereNotNull('preferences')
}
getActiveCustomers(): Collection<CustomerData> {
return this.customers
.whereNotNull('lastPurchase')
.filter(customer => {
const lastPurchase = new Date(customer.lastPurchase!)
const thirtyDaysAgo = new Date()
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
return lastPurchase >= thirtyDaysAgo
})
}
}Type Safety
typescript
interface TypedProduct {
id: number
name: string
description: string | null
price: number | null
}
const products = collect<TypedProduct>([
{ id: 1, name: 'A', description: null, price: 100 },
{ id: 2, name: 'B', description: 'Test', price: null }
])
// Type-safe not-null checks
const withDescription = products.whereNotNull('description')
const withPrice = products.whereNotNull('price')
// TypeScript enforces valid keys and nullable types
// products.whereNotNull('name') // ✗ TypeScript error for non-nullable field
// products.whereNotNull('invalid') // ✗ TypeScript error for invalid keyReturn Value
- Returns a new Collection containing only items where the specified key is not null
- Original collection remains unchanged
- Maintains type safety with TypeScript
- Can be chained with other collection methods
- Excludes both null and undefined values
- Empty collection if no matches found
Common Use Cases
1. Product Management
- Complete listings
- Valid products
- Active items
- Publishable content
- Available items
2. Order Processing
- Trackable shipments
- Valid orders
- Complete information
- Active deliveries
- Processable orders
3. Customer Management
- Valid contacts
- Complete profiles
- Active customers
- Marketable users
- Segmented customers
4. Inventory Control
- Available stock
- Valid items
- Active products
- Trackable inventory
- Complete records
5. Marketing Analysis
- Valid segments
- Complete campaigns
- Active promotions
- Trackable metrics
- Analyzable data
6. Data Validation
- Complete records
- Valid entries
- Active status
- Required fields
- Quality checks
7. Reporting
- Valid metrics
- Complete data
- Active periods
- Analyzable records
- Valid comparisons
8. User Management
- Active users
- Valid accounts
- Complete profiles
- Verified users
- Contactable customers
9. Content Management
- Published content
- Valid entries
- Complete articles
- Active listings
- Viewable items
10. Analytics
- Valid metrics
- Complete datasets
- Active tracking
- Analyzable periods
- Reportable data