3.6 KiB
targeting.ts — Targeting Rule Evaluation
(no submodules)
Purpose
Provides the evaluateTargeting function that evaluates an ordered list of
targeting rules against a set of user attributes. The function implements AND
semantics — every rule in the list must pass for the user to be considered
eligible for the experiment. This single-function module is intentionally
small and pure: it has no side effects, no I/O, no external dependencies, and
is trivially unit-testable.
Targeting rules are the primary mechanism for gating experiment exposure to specific user segments. Common use cases include restricting to paid users, specific geographic regions, device types, or beta-program membership.
Features
- Eight comparison operators:
eq,neq,in,notIn,gt,lt,gte,lte - Numeric ordering operators (
gt,lt,gte,lte) require both sides to be numbers; any type mismatch returnsfalserather than throwing in/notInaccept any array on the right-hand side- An empty rules array always returns
true(no restriction) - Absent attributes evaluate to
undefinedand fail equality/ordering tests gracefully without exceptions
Usage: Basic Example
import { evaluateTargeting } from '@suaveplan/ab-testing/targeting';
const eligible = evaluateTargeting(
[{ attribute: 'plan', operator: 'eq', value: 'premium' }],
{ plan: 'premium', country: 'US' }
);
console.log(eligible); // true
Usage: Advanced Example
import { evaluateTargeting } from '@suaveplan/ab-testing/targeting';
// Multi-rule targeting: premium users in North America with high session count
const rules = [
{ attribute: 'plan', operator: 'eq' as const, value: 'premium' },
{ attribute: 'country', operator: 'in' as const, value: ['US', 'CA', 'MX'] },
{ attribute: 'sessionCount', operator: 'gte' as const, value: 10 },
{ attribute: 'blocklisted', operator: 'neq' as const, value: true },
];
const user1 = { plan: 'premium', country: 'CA', sessionCount: 15, blocklisted: false };
const user2 = { plan: 'free', country: 'US', sessionCount: 30, blocklisted: false };
console.log(evaluateTargeting(rules, user1)); // true (all 4 rules pass)
console.log(evaluateTargeting(rules, user2)); // false (plan !== 'premium')
API Reference
evaluateTargeting(rules, attributes): boolean
rules—ReadonlyArray<TargetingRule>— ordered list of predicatesattributes—UserAttributes(Record<string, string | number | boolean>)- Returns —
boolean—trueiff every rule is satisfied (orrulesis empty)
Supported operators
| Operator | Description | RHS type |
|---|---|---|
eq |
Strict equality (===) |
any |
neq |
Strict inequality (!==) |
any |
in |
LHS is contained in RHS array | unknown[] |
notIn |
LHS is not contained in RHS array | unknown[] |
gt |
LHS > RHS | number |
lt |
LHS < RHS | number |
gte |
LHS >= RHS | number |
lte |
LHS <= RHS | number |
Implementation Notes
All comparisons are intentionally strict (=== / !==) to avoid surprising
truthy/falsy coercions. When the RHS is not of the expected type for ordering
operators (e.g. a string is passed as the threshold for gt), the function
returns false rather than throwing, making it safe to evaluate partially
invalid rule sets without crashing the assignment pipeline.
The in / notIn operators use Array.isArray to check the RHS type before
calling Array.prototype.includes. When the RHS is not an array, the rule
evaluates to false.