← Strategy lesson
Lab

Strategy

type SearchResult = { id: string; score: number; ageDays: number };

// A policy compares two results. Negative: a first. Zero: tied. Positive: b first.
type RankingPolicy = (a: SearchResult, b: SearchResult) => number;

function byRelevance(a: SearchResult, b: SearchResult): number {
  return b.score - a.score;
}
function byRecent(a: SearchResult, b: SearchResult): number {
  return a.ageDays - b.ageDays;
}

// The shared workflow: copy, ask the policy, and settle its ties by ID.
function rankResults(items: SearchResult[], policy: RankingPolicy): SearchResult[] {
  const ranked = [...items];
  function compare(a: SearchResult, b: SearchResult): number {
    const order = policy(a, b);
    const tied = order === 0;
    if (!tied) return order;
    return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
  }
  ranked.sort(compare);
  return ranked;
}

const results: SearchResult[] = [
  { id: 'cache', score: 90, ageDays: 30 },
  { id: 'api', score: 90, ageDays: 7 },
  { id: 'release', score: 65, ageDays: 1 },
];

const ids = (items: SearchResult[]) => items.map((item) => item.id).join(', ');
const relevance = rankResults(results, byRelevance);
const recent = rankResults(results, byRecent);
console.log(`relevance: ${ids(relevance)}`);
console.log(`recent: ${ids(recent)}`);
console.log(`as returned: ${ids(results)}`);