Overview
Equality operators compare values for equality or inequality. Rule Engine JS provides two equality comparison operators:
eq
Tests if two values are equal
neq
Tests if two values are not equal
Architecture
Equality operators are implemented in the ComparisonOperators class which extends BaseOperator:
Source Files:
- Equality operators:
src/operators/comparison.js
- Base operator:
src/operators/base/BaseOperator.js
- Type utilities:
src/utils/TypeUtils.js
- Unit tests:
tests/unit/operators/comparison.test.js
Key Features
- Dynamic field comparison - Compare two fields or a field to a literal value
- Strict/loose modes - Control type coercion behavior (
== vs ===)
- Type-safe equality - Handles primitives, objects, arrays, null, undefined
- Comprehensive validation - Validates argument count and types
eq - Equals
Tests if two values are equal.
Syntax
{
eq: [left, right];
}
{
eq: [left, right, options];
}
Parameters
Left operand - field path or literal value
Right operand - field path or literal value
Configuration options
Enable strict equality (===) instead of loose (==)
Returns
boolean - true if values are equal, false otherwise
Examples
Basic Equality
Dynamic Field Comparison
Strict vs Loose Mode
With Rule Helpers
import { createRuleEngine } from 'rule-engine-js';
const engine = createRuleEngine();
const data = {
user: {
name: 'John Doe',
age: 28,
active: true
}
};
// String equality
engine.evaluateExpr({ eq: ['user.name', 'John Doe'] }, data);
// Result: { success: true, value: true }
// Numeric equality
engine.evaluateExpr({ eq: ['user.age', 28] }, data);
// Result: { success: true, value: true }
// Boolean equality
engine.evaluateExpr({ eq: ['user.active', true] }, data);
// Result: { success: true, value: true }
// Fails when not equal
engine.evaluateExpr({ eq: ['user.name', 'Jane Doe'] }, data);
// Result: { success: true, value: false }
Common Use Cases
Role-Based Access Control
const user = {
role: 'admin',
status: 'active',
department: 'engineering'
};
const canAccessAdminPanel = {
and: [
{ eq: ['role', 'admin'] },
{ eq: ['status', 'active'] }
]
};
engine.evaluateExpr(canAccessAdminPanel, user);
// Result: { success: true, value: true }
const config = {
environment: 'production',
debugMode: false,
maintenanceMode: false
};
const canServeTraffic = {
and: [
{ eq: ['environment', 'production'] },
{ eq: ['debugMode', false] },
{ eq: ['maintenanceMode', false] }
]
};
engine.evaluateExpr(canServeTraffic, config);
// Result: { success: true, value: true }
const data = {
user: {
name: 'John',
middleName: null
// lastName is undefined
}
};
// Check for null
engine.evaluateExpr({ eq: ['user.middleName', null] }, data);
// Result: { success: true, value: true }
// Undefined field
engine.evaluateExpr({ eq: ['user.lastName', undefined] }, data);
// Result: { success: true, value: true }
// Note: Consider using isNull/isNotNull operators instead
Type Coercion: By default, eq uses loose equality (==). Use { strict: true } or create a strict engine for type-safe comparisons.
neq - Not Equal
Tests if two values are not equal (inverse of eq).
Syntax
{
neq: [left, right];
}
{
neq: [left, right, options];
}
Parameters
Left operand - field path or literal value
Right operand - field path or literal value
Configuration options
Enable strict inequality (!==) instead of loose (!=)
Returns
boolean - true if values are not equal, false otherwise
Examples
const data = {
user: {
status: 'active',
role: 'editor'
}
};
// Ensure not inactive
engine.evaluateExpr({ neq: ['user.status', 'inactive'] }, data);
// Result: { success: true, value: true }
// Fails when equal
engine.evaluateExpr({ neq: ['user.status', 'active'] }, data);
// Result: { success: true, value: false }
// Multiple exclusions
const notBannedOrSuspended = {
and: [
{ neq: ['user.status', 'banned'] },
{ neq: ['user.status', 'suspended'] }
]
};
engine.evaluateExpr(notBannedOrSuspended, data);
// Result: { success: true, value: true }
Common Use Cases
const user = {
role: 'editor',
status: 'active',
accountType: 'premium'
};
// Not a basic user
const hasAdvancedAccess = {
and: [
{ neq: ['role', 'viewer'] },
{ neq: ['accountType', 'free'] },
{ eq: ['status', 'active'] }
]
};
engine.evaluateExpr(hasAdvancedAccess, user);
// Result: { success: true, value: true }
const form = {
email: 'user@example.com',
alternateEmail: 'alternate@example.com'
};
// Emails must be different
const uniqueEmails = { neq: ['email', 'alternateEmail'] };
engine.evaluateExpr(uniqueEmails, form);
// Result: { success: true, value: true }
const workflow = {
currentState: 'pending',
previousState: 'draft'
};
// Ensure state actually changed
const stateChanged = {
neq: ['currentState', 'previousState']
};
engine.evaluateExpr(stateChanged, workflow);
// Result: { success: true, value: true }
For checking if a value is NOT in a list, prefer the notIn operator instead of multiple neq
conditions.
Error Handling
Common Errors
// Missing second argument
const result = engine.evaluateExpr({ eq: ['user.name'] }, data);
// Returns:
// {
// success: false,
// error: "EQ operator requires 2-3 arguments, got 1"
// }
// Missing array brackets
const result = engine.evaluateExpr({ eq: 'user.name' }, data);
// Returns:
// {
// success: false,
// error: "EQ operator requires array arguments"
// }
const data = { user: { name: 'John' } };
// Field doesn't exist - not an error, returns false
const result = engine.evaluateExpr({ eq: ['user.age', 25] }, data);
// Returns:
// {
// success: true,
// value: false // undefined !== 25
// }
Error Recovery
function safeEquals(engine, field, expected, data, fallback = false) {
const result = engine.evaluateExpr({ eq: [field, expected] }, data);
if (!result.success) {
console.error('Evaluation failed:', result.error);
return fallback;
}
return result.value;
}
// Usage
const isAdmin = safeEquals(engine, 'user.role', 'admin', userData, false);
Type Coercion
Equality operators support both strict and loose comparison modes:
| Mode | Symbol | Behavior | Example |
| Loose (default) | == / != | Type coercion enabled | 25 == '25' → true |
| Strict | === / !== | No type coercion | 25 === '25' → false |
Setting Strict Mode
// All rules use strict comparison
const engine = createRuleEngine({ strict: true });
engine.evaluateExpr({ eq: ['age', '25'] }, { age: 25 });
// Result: { success: true, value: false }
Use strict mode in production to prevent unexpected type coercion bugs.
API Reference
For complete API documentation: