TypeDrop
2026-06-23 Challenge
2026-06-23
Medium
Typed Feature Flag Evaluator with Targeting Rules & Rollout
You're building the feature-flag evaluation engine for a SaaS platform. Raw flag configurations arrive as `unknown` from a remote config service; your evaluator must validate them, match each flag's targeting rules against a typed user context, apply percentage-based rollouts, and return a strongly-typed evaluation report — with zero `any`.
Goals
- Implement `parseFlag` to validate `unknown` flag configs into `FeatureFlag` using only type-narrowing guards (no `as`).
- Implement `evaluateFlag` to apply targeting rules in order using all five `RuleOperator` semantics, respecting the disabled and rollout-bucket checks.
- Implement `evaluateFlags` to orchestrate parsing and evaluation, skip invalid flags into an errors array, and produce a fully-typed `EvaluationReport`.
- Ensure `rolloutPercentage` correctly gates non-default variants using `deterministicHash(flagKey:userId) % 100`.
challenge.ts
export type RuleOperator = "eq" | "neq" | "in" | "gt" | "lt";
export interface FeatureFlag {
key: string;
description: string;
enabled: boolean;
rules: TargetingRule[];
defaultVariant: string;
rolloutPercentage: number; // 0–100
}
export interface UserContext {
userId: string;
email: string;
country: string;
plan: "free" | "pro" | "enterprise";
accountAgeDays: number;
}
export type Result<T, E> =
| { ok: true; value: T }
| { ok: false; error: E };
// Validate raw unknown → FeatureFlag
export function parseFlag(raw: unknown, index: number): Result<FeatureFlag, ValidationError>;
// Evaluate one flag for a user → variant + reason
export function evaluateFlag(flag: FeatureFlag, user: UserContext): FlagEvaluation;
// Parse all raws, evaluate each, return a typed report
export function evaluateFlags(
rawFlags: unknown[], user: UserContext, errors: ValidationError[]
): EvaluationReport;
Hints (click to reveal)
Hints
- For `parseFlag`, build up a validated object field-by-field using `typeof` and `Array.isArray` checks — `keyof UserContext` can be validated against a hard-coded set like `new Set(["userId", "email", ...])`.
- In `evaluateFlag`, handle the four evaluation steps in strict order (disabled → rollout → rules → default) before touching any rule logic.
- For the `"in"` operator, remember `ruleValue` must be `string[]` — narrow it with `Array.isArray` before calling `.includes`.
Useful resources
Or clone locally
git clone -b challenge/2026-06-23 https://github.com/niltonheck/typedrop.git