Filter arrays like a pro. A powerful, SQL-like array filtering library for TypeScript with advanced pattern matching, MongoDB-style operators, deep object comparison, geospatial queries, and zero dependencies.
Quick Start โข Why You'll Love It โข Examples โข Playground โข Documentation
- @mcabreradev/filter
Tired of writing complex filter logic? Stop wrestling with nested Array.filter() chains and verbose conditionals. Write clean, declarative filters that read like queries.
Before:
const results = data.filter(item => item.age >= 18 && item.status === 'active' && (item.role === 'admin' || item.role === 'moderator') && item.email.endsWith('@company.com') && item.createdAt >= thirtyDaysAgo );After:
const results = filter(data, { age: { $gte: 18 }, status: 'active', role: ['admin', 'moderator'], email: { $endsWith: '@company.com' }, createdAt: { $gte: thirtyDaysAgo } });Same result. 70% less code. 100% more readable.
npm install @mcabreradev/filter # or pnpm add @mcabreradev/filter # or yarn add @mcabreradev/filterRequirements: Node.js >= 20, TypeScript 5.0+ (optional)
import { filter } from '@mcabreradev/filter'; const users = [ { name: 'Alice', age: 30, city: 'Berlin', active: true }, { name: 'Bob', age: 25, city: 'London', active: false }, { name: 'Charlie', age: 35, city: 'Berlin', active: true } ]; // Simple string search const berlinUsers = filter(users, 'Berlin'); // โ [{ name: 'Alice', ... }, { name: 'Charlie', ... }] // Object-based filtering const activeBerlinUsers = filter(users, { city: 'Berlin', active: true }); // โ [{ name: 'Alice', ... }] // MongoDB-style operators const adults = filter(users, { age: { $gte: 18 } }); // โ All users (all are 18+) // That's it! You're filtering like a pro.๐ฎ Try it in the Playground โ
- 530x faster with optional caching
- 500x faster with lazy evaluation for large datasets
- Optimized for production workloads
- Intuitive API that feels natural
- SQL-like syntax you already know
- Full TypeScript support with intelligent autocomplete
- Multiple filtering strategies (strings, objects, operators, predicates)
- Works with any data structure
- Combine approaches seamlessly
- 993+ tests ensuring reliability
- Zero dependencies (12KB gzipped)
- Used in production by companies worldwide
- MIT licensed
- Truly zero dependencies!
- Tiny 12KB bundle
- Optional Zod for validation
- No bloat, just pure filtering power
- Built with strict TypeScript
- Catch errors at compile time
- Full IntelliSense and autocomplete support
- Works everywhere: React, Vue, Svelte, Angular, SolidJS, Preact
- First-class hooks and composables included
- SSR compatible (Next.js, Nuxt, SvelteKit)
- Process millions of records efficiently
- Lazy evaluation for memory optimization
- Built for scale
// String matching - searches all properties filter(products, 'Laptop'); // Object matching - AND logic filter(products, { category: 'Electronics', price: { $lt: 1000 } }); // Wildcard patterns (SQL-like) filter(users, '%alice%'); // Contains 'alice' filter(users, 'Al%'); // Starts with 'Al' filter(users, '%son'); // Ends with 'son'// Comparison operators filter(products, { price: { $gte: 100, $lte: 500 } }); // Array operators filter(products, { category: { $in: ['Electronics', 'Books'] }, tags: { $contains: 'sale' } }); // String operators filter(users, { email: { $endsWith: '@company.com' }, name: { $startsWith: 'John' } }); // Logical operators filter(products, { $and: [ { inStock: true }, { $or: [ { rating: { $gte: 4.5 } }, { price: { $lt: 50 } } ] } ] });// Clean array syntax - no $in needed! filter(products, { category: ['Electronics', 'Books'] }); // Equivalent to: { category: { $in: ['Electronics', 'Books'] } } // Multiple properties filter(users, { city: ['Berlin', 'Paris'], role: ['admin', 'moderator'] });import { filter, type GeoPoint } from '@mcabreradev/filter'; const userLocation: GeoPoint = { lat: 52.52, lng: 13.405 }; // Find restaurants within 5km filter(restaurants, { location: { $near: { center: userLocation, maxDistanceMeters: 5000 } }, rating: { $gte: 4.5 } });// Events in next 7 days filter(events, { date: { $upcoming: { days: 7 } } }); // Recent events (last 24 hours) filter(events, { date: { $recent: { hours: 24 } } }); // Weekday events during business hours filter(events, { date: { $dayOfWeek: [1, 2, 3, 4, 5] }, startTime: { $timeOfDay: { start: 9, end: 17 } } }); // Users who logged in recently (last 7 days) filter(users, { lastLogin: { $recent: { days: 7 } } }); // Upcoming meetings in next 2 hours filter(meetings, { startTime: { $upcoming: { hours: 2 } } }); // Weekend events only filter(events, { date: { $isWeekend: true } }); // Calculate age (users over 18) filter(users, { birthDate: { $age: { $gte: 18 } } }); // Events before a specific date filter(events, { date: { $isBefore: new Date('2025-12-31') } });// Enable caching for repeated queries const results = filter(largeDataset, expression, { enableCache: true, orderBy: { field: 'price', direction: 'desc' }, limit: 100 }); // Lazy evaluation for large datasets import { filterFirst } from '@mcabreradev/filter'; const first10 = filterFirst(users, { premium: true }, 10);interface Product { id: number; name: string; price: number; category: string; brand: string; rating: number; inStock: boolean; tags: string[]; } const products: Product[] = [...]; // Find affordable, highly-rated electronics in stock const affordableElectronics = filter(products, { category: 'Electronics', price: { $lte: 1000 }, rating: { $gte: 4.5 }, inStock: true }); // Search with multiple filters const searchResults = filter(products, { name: { $contains: 'laptop' }, brand: { $in: ['Apple', 'Dell', 'HP'] }, price: { $gte: 500, $lte: 2000 } }); // Sort results const sortedProducts = filter(products, { category: 'Electronics', inStock: true }, { orderBy: [ { field: 'price', direction: 'asc' }, { field: 'rating', direction: 'desc' } ], limit: 20 });Works seamlessly with your favorite framework:
import { useFilter } from '@mcabreradev/filter/react'; function UserList() { const { filtered, isFiltering } = useFilter(users, { active: true }); return <div>{filtered.map(u => <User key={u.id} {...u} />)}</div>; }<script setup> import { useFilter } from '@mcabreradev/filter/vue'; const { filtered } = useFilter(users, { active: true }); </script><script> import { useFilter } from '@mcabreradev/filter/svelte'; const { filtered } = useFilter(users, writable({ active: true })); </script>import { FilterService } from '@mcabreradev/filter/angular'; @Component({ providers: [FilterService], template: ` @for (user of filterService.filtered(); track user.id) { <div>{{ user.name }}</div> } ` }) export class UserListComponent { filterService = inject(FilterService<User>); }import { useFilter } from '@mcabreradev/filter/solidjs'; function UserList() { const { filtered } = useFilter( () => users, () => ({ active: true }) ); return <For each={filtered()}>{(u) => <div>{u.name}</div>}</For>; }import { useFilter } from '@mcabreradev/filter/preact'; function UserList() { const { filtered } = useFilter(users, { active: true }); return <div>{filtered.map(u => <div key={u.id}>{u.name}</div>)}</div>; }Features:
- โ Full TypeScript support with generics
- โ Debounced search hooks/services
- โ Pagination support
- โ SSR compatible
- โ 100% test coverage
๐ Complete Framework Guide โ
Comparison: $gt, $gte, $lt, $lte, $eq, $ne Array: $in, $nin, $contains, $size String: $startsWith, $endsWith, $contains, $regex, $match Logical: $and, $or, $not Geospatial: $near, $geoBox, $geoPolygon Datetime: $recent, $upcoming, $dayOfWeek, $timeOfDay, $age, $isWeekday, $isWeekend, $isBefore, $isAfter
Full type safety with intelligent autocomplete:
interface Product { name: string; price: number; tags: string[]; } filter<Product>(products, { price: { }, // Autocomplete: $gt, $gte, $lt, $lte, $eq, $ne name: { }, // Autocomplete: $startsWith, $endsWith, $contains, $regex tags: { } // Autocomplete: $in, $nin, $contains, $size });filter(data, expression, { caseSensitive: false, // Case-sensitive string matching maxDepth: 3, // Max depth for nested objects enableCache: true, // Enable result caching (530x faster) orderBy: 'price', // Sort results limit: 10, // Limit number of results debug: true // Visual debugging mode });Efficiently process large datasets with lazy evaluation:
import { filterLazy, filterFirst, filterExists, filterCount } from '@mcabreradev/filter'; // Process items on-demand const filtered = filterLazy(millionRecords, { active: true }); for (const item of filtered) { process(item); if (shouldStop) break; // Early exit } // Find first N matches const first10 = filterFirst(users, { premium: true }, 10); // Check existence without processing all items const hasAdmin = filterExists(users, { role: 'admin' }); // Count matches const activeCount = filterCount(users, { active: true });Benefits:
- ๐ 500x faster for operations that don't need all results
- ๐พ 100,000x less memory for large datasets
- โก Early exit optimization
๐ Lazy Evaluation Guide โ
530x faster with optional caching:
// First call - processes data const results = filter(largeDataset, { age: { $gte: 18 } }, { enableCache: true }); // Second call - returns cached result instantly const sameResults = filter(largeDataset, { age: { $gte: 18 } }, { enableCache: true });Performance Gains:
| Scenario | Without Cache | With Cache | Speedup |
|---|---|---|---|
| Simple query (10K items) | 5.3ms | 0.01ms | 530x |
| Regex pattern | 12.1ms | 0.02ms | 605x |
| Complex nested | 15.2ms | 0.01ms | 1520x |
Built-in debug mode with expression tree visualization:
filter(users, { city: 'Berlin' }, { debug: true }); // Console output: // โโ Filter Debug Tree // โ Expression: {"city":"Berlin"} // โ Matched: 3/10 (30.0%) // โ Execution time: 0.42ms // โโ โ city = "Berlin"๐ Debug Guide โ
- Getting Started - Installation and first steps
- All Operators - Complete operator reference
- Geospatial Queries - Location-based filtering
- Datetime Operators - Temporal filtering
- Framework Integrations - React, Vue, Svelte, Angular, SolidJS, Preact
- Lazy Evaluation - Efficient large dataset processing
- Memoization & Caching - Performance optimization
- Visual Debugging - Debug mode and tree visualization
Filter is optimized for performance:
- Operators use early exit strategies for fast evaluation
- Regex patterns are compiled and cached
- Optional caching for repeated queries (530x-1520x faster)
- Lazy evaluation for efficient large dataset processing (500x faster)
- Type guards for fast type checking
// โ
Fast: Operators with early exit filter(data, { age: { $gte: 18 } }); // โ
Fast with caching for repeated queries filter(largeData, expression, { enableCache: true }); // โ
Fast with lazy evaluation for large datasets const result = filterFirst(millionRecords, { active: true }, 100);| Import | Size (gzipped) | Tree-Shakeable |
|---|---|---|
| Full | 12 KB | โ |
| Core only | 8.4 KB | โ |
| React hooks | 9.2 KB | โ |
| Lazy evaluation | 5.4 KB | โ |
Works in all modern browsers and Node.js:
- Node.js: >= 20
- Browsers: Chrome, Firefox, Safari, Edge (latest versions)
- TypeScript: >= 5.0
- Module Systems: ESM, CommonJS
Good news: v5.x is 100% backward compatible! All v3.x code continues to work.
// โ
All v3.x syntax still works filter(data, 'string'); filter(data, { prop: 'value' }); filter(data, (item) => true); filter(data, '%pattern%'); // โ
New in v5.x filter(data, { age: { $gte: 18 } }); filter(data, expression, { enableCache: true });๐ Migration Guide โ
- ๐ Bug Fix: Fixed critical issue where
limitoption was ignored in cache key - โก Performance: Replaced unbounded caches with LRU strategy to prevent memory leaks
- ๐ Stability: Improved memory management for long-running applications
- ๐จ New Framework Integrations: Angular, SolidJS, and Preact support
- ๐ข Limit Option: New
limitconfiguration option to restrict result count - ๐ OrderBy Option: New
OrderByconfiguration option to sort filtered results by field(s) in ascending or descending order - โ 993+ tests with comprehensive coverage
๐ ฐ๏ธ Angular: Services and Pipes with Signals support- ๐ท SolidJS: Signal-based reactive hooks
- โก Preact: Lightweight hooks API
- ๐ Geospatial Operators: Location-based filtering with $near, $geoBox, $geoPolygon
- ๐ Datetime Operators: Temporal filtering with $recent, $upcoming, $dayOfWeek, $age
- ๐จ Array OR Syntax: Intuitive array-based OR filtering
- ๐ Visual Debugging: Built-in debug mode with expression tree visualization
- ๐ฎ Interactive Playground: Online playground for testing filters
๐ Full Changelog โ
We welcome contributions! Please read our Contributing Guide for details.
Ways to Contribute:
- Report bugs or request features via GitHub Issues
- Submit pull requests with bug fixes or new features
- Improve documentation
- Share your use cases and examples
MIT License - see LICENSE.md for details.
Copyright (c) 2025 Miguelangel Cabrera
- ๐ Complete Documentation
- ๐ฌ GitHub Discussions
- ๐ Issue Tracker
- โญ Star on GitHub
Made with โค๏ธ for the JavaScript/TypeScript community