Skip to main content

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
string | any
required
Left operand - field path or literal value
right
string | any
required
Right operand - field path or literal value
options
object
Configuration options

Returns

boolean - true if values are equal, false otherwise

Examples

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

const registration = {
  password: 'SecurePass123!',
  confirmPassword: 'SecurePass123!',
  email: 'user@example.com',
  confirmEmail: 'user@example.com'
};

const validation = {
  and: [
    { eq: ['password', 'confirmPassword'] },
    { eq: ['email', 'confirmEmail'] }
  ]
};

engine.evaluateExpr(validation, registration);
// Result: { success: true, value: true }
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
string | any
required
Left operand - field path or literal value
right
string | any
required
Right operand - field path or literal value
options
object
Configuration options

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:
ModeSymbolBehaviorExample
Loose (default)== / !=Type coercion enabled25 == '25'true
Strict=== / !==No type coercion25 === '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.

Numeric Operators

GT, GTE, LT, LTE

Special Operators

isNull, isNotNull, between

Array Operators

in, notIn

Logical Operators

and, or, not

State Operators

changed, changedTo, changedFrom

All Operators

Complete operator reference

API Reference

For complete API documentation: