Memoization caches results of a function for given inputs, so repeated calls reuse the cached value. It helps when you have overlapping subproblems (common in dynamic programming) and the same states are computed many times.
function fib(n: number, memo = new Map<number, number>()): number {
if (n <= 1) return n;
const cached = memo.get(n);
if (cached !== undefined) return cached;
const value = fib(n - 1, memo) + fib(n - 2, memo);
memo.set(n, value);
return value;
}