Skip to content

Operator Autocomplete ​

The library provides intelligent operator autocomplete based on the type of each property. TypeScript will automatically suggest only the valid operators for each data type.

Preview ​

typescript
// When you type this in your editor:
filter(users, {
  age: { $ // <- Press Ctrl+Space here

// TypeScript shows:
// ┌─────────────────────────────────────┐
// │ ✓ $gt     - Greater than            │
// │ ✓ $gte    - Greater than or equal   │
// │ ✓ $lt     - Less than               │
// │ ✓ $lte    - Less than or equal      │
// │ ✓ $eq     - Equal                   │
// │ ✓ $ne     - Not equal               │
// └─────────────────────────────────────┘

Only valid operators for numbers! You won't see $startsWith or $regex because they don't make sense for numbers.

How It Works ​

The type system analyzes each property of your interface and provides the appropriate operators:

  • Strings: $startsWith, $endsWith, $contains, $regex, $match, $eq, $ne
  • Numbers: $gt, $gte, $lt, $lte, $eq, $ne
  • Dates: $gt, $gte, $lt, $lte, $eq, $ne
  • Arrays: $in, $nin, $contains, $size
  • Booleans: $eq, $ne

Usage Examples ​

Numeric Operators ​

typescript
interface User {
  age: number;
  score: number;
}

const users: User[] = [];

// TypeScript autocompletes: $gt, $gte, $lt, $lte, $eq, $ne
filter(users, {
  age: {
    $gte: 18,  // ✅ Valid
    $lt: 65    // ✅ Valid
  }
});

String Operators ​

typescript
interface Product {
  name: string;
  category: string;
}

const products: Product[] = [];

// TypeScript autocompletes: $startsWith, $endsWith, $contains, $regex, $match, $eq, $ne
filter(products, {
  name: {
    $startsWith: 'Laptop',  // ✅ Valid
    $regex: /^Lap/i         // ✅ Valid
  }
});

Array Operators ​

typescript
interface User {
  tags: string[];
  roles: string[];
}

const users: User[] = [];

// TypeScript autocompletes: $in, $nin, $contains, $size
filter(users, {
  tags: {
    $contains: 'admin',  // ✅ Valid
    $size: 3             // ✅ Valid
  }
});

Boolean Operators ​

typescript
interface User {
  isActive: boolean;
  isPremium: boolean;
}

const users: User[] = [];

// TypeScript autocompletes: $eq, $ne
filter(users, {
  isActive: {
    $eq: true  // ✅ Valid
  }
});

Date Operators ​

typescript
interface Event {
  createdAt: Date;
  updatedAt: Date;
}

const events: Event[] = [];

// TypeScript autocompletes: $gt, $gte, $lt, $lte, $eq, $ne
filter(events, {
  createdAt: {
    $gte: new Date('2024-01-01'),  // ✅ Valid
    $lt: new Date('2025-01-01')    // ✅ Valid
  }
});

Combining Operators ​

You can combine multiple operators in a single query:

typescript
interface User {
  name: string;
  age: number;
  tags: string[];
  isActive: boolean;
  createdAt: Date;
}

const users: User[] = [];

filter(users, {
  name: { $startsWith: 'John' },
  age: { $gte: 18, $lt: 65 },
  tags: { $contains: 'verified' },
  isActive: { $eq: true },
  createdAt: { $gte: new Date('2024-01-01') }
});

Logical Operators ​

Logical operators are also available with autocomplete:

typescript
filter(users, {
  $or: [
    { age: { $lt: 18 } },
    { age: { $gte: 65 } }
  ],
  isActive: { $eq: true }
});

filter(users, {
  $and: [
    { name: { $startsWith: 'A' } },
    { score: { $gt: 100 } }
  ]
});

filter(users, {
  $not: {
    isActive: { $eq: false }
  }
});

Type Safety ​

The type system prevents errors at compile time:

typescript
interface User {
  age: number;
  name: string;
}

// ❌ Error: $startsWith is not valid for numbers
filter(users, {
  age: {
    $startsWith: '25'  // TypeScript marks this as an error
  }
});

// ❌ Error: $gt is not valid for strings (although it technically works)
filter(users, {
  name: {
    $gt: 'John'  // TypeScript marks this as an error
  }
});

Nested Object Support ​

The autocomplete system supports deeply nested objects up to 4 levels:

typescript
interface User {
  name: string;
  address: {
    city: string;
    coordinates: {
      lat: number;
      lng: number;
    };
  };
  settings: {
    privacy: {
      showEmail: boolean;
    };
  };
}

// ✅ Level 1: Root properties
filter(users, {
  name: { $startsWith: 'John' }  // Autocompletes string operators
});

// ✅ Level 2: Nested objects
filter(users, {
  address: {
    city: { $startsWith: 'New' }  // Autocompletes string operators
  }
});

// ✅ Level 3: Deeply nested objects
filter(users, {
  address: {
    coordinates: {
      lat: { $gte: -90, $lte: 90 }  // Autocompletes number operators
    }
  }
});

// ✅ Level 4: Very deeply nested objects
filter(users, {
  settings: {
    privacy: {
      showEmail: { $eq: true }  // Autocompletes boolean operators
    }
  }
});

Complex Nested Queries ​

You can combine multiple nested levels in a single query:

typescript
filter(users, {
  name: { $startsWith: 'J' },
  address: {
    city: { $eq: 'New York' },
    coordinates: {
      lat: { $gte: 40, $lte: 41 }
    }
  },
  settings: {
    privacy: {
      showEmail: { $eq: true }
    }
  }
});

Logical Operators with Nested Objects ​

typescript
filter(users, {
  $or: [
    {
      address: {
        city: { $eq: 'New York' }
      }
    },
    {
      address: {
        city: { $eq: 'Los Angeles' }
      }
    }
  ]
});

Mixed Syntax ​

You can mix direct values with operators at different nesting levels:

typescript
filter(users, {
  address: {
    country: 'USA',              // Direct value
    city: { $startsWith: 'New' } // Operator
  }
});

Editor Support ​

Autocomplete works in any editor with TypeScript support:

  • VS Code/Cursor: Press Ctrl+Space (Windows/Linux) or Cmd+Space (Mac)
  • WebStorm: Autocomplete appears automatically
  • Vim/Neovim: With LSP configured (coc.nvim, nvim-lsp)
  • Sublime Text: With LSP-typescript

Benefits ​

  1. Discovery: Discover available operators without consulting documentation
  2. Error Prevention: TypeScript prevents the use of incorrect operators
  3. Productivity: Write code faster with intelligent suggestions
  4. Maintainability: Code is easier to understand and maintain
  5. Safe Refactoring: Type changes propagate automatically

Notes ​

  • Autocomplete is only a TypeScript feature at development time
  • It doesn't affect bundle size or runtime performance
  • It's 100% backward compatible with existing code
  • Works with TypeScript interfaces, types, and classes

Released under the MIT License.