typescript 35 lines · 6 steps

Streaming running averages in TypeScript

Two takes on incremental aggregation: a stateful class and a lazy generator that emit stats one value at a time.

Explained by highlit
1interface RunningStats {
2 count: number;
3 total: number;
4 average: number;
5}
6 
7class RunningAggregator {
8 private count = 0;
9 private total = 0;
10 
11 push(value: number): RunningStats {
12 this.count += 1;
13 this.total += value;
14 return this.snapshot();
15 }
16 
17 snapshot(): RunningStats {
18 return {
19 count: this.count,
20 total: this.total,
21 average: this.count === 0 ? 0 : this.total / this.count,
22 };
23 }
24}
25 
26function* runningStats(source: Iterable<number>): Generator<RunningStats> {
27 let count = 0;
28 let total = 0;
29 
30 for (const value of source) {
31 count += 1;
32 total += value;
33 yield { count, total, average: total / count };
34 }
35}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Maintaining a running count and total lets you compute an average in O(1) per value without rescanning history.
  2. 2A class holds state across separate calls, while a generator threads state through a single lazy iteration.
  3. 3Returning an immutable snapshot object keeps internal accumulators private and safe from outside mutation.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Streaming running averages in TypeScript — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code