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
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Maintaining a running count and total lets you compute an average in O(1) per value without rescanning history.
- 2A class holds state across separate calls, while a generator threads state through a single lazy iteration.
- 3Returning an immutable snapshot object keeps internal accumulators private and safe from outside mutation.
Related explainers
typescript
import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; import localeFrExtra from '@angular/common/locales/extra/fr'; import localeDe from '@angular/common/locales/de';
Locale-aware bootstrapping in Angular
i18n
localization
dependency-injection
Intermediate
8 steps
typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import * as Joi from 'joi';
Validating env config at boot in NestJS
configuration
schema-validation
environment-variables
Intermediate
8 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { InjectRepository } from '@nestjs/typeorm';
A cache-aside country lookup in NestJS
cache-aside
dependency-injection
batch-lookup
Intermediate
8 steps
rust
use std::f64::consts::PI; #[derive(Debug, Clone, Copy)] pub struct LatLng {
Building geographic bounding boxes in Rust
geospatial
value-types
option
Intermediate
7 steps
typescript
import { Injectable, effect, signal, computed } from '@angular/core'; interface Preferences { theme: 'light' | 'dark';
A signal-based preferences store in Angular
signals
state-management
persistence
Intermediate
7 steps
python
import random from typing import Iterator, List
How reservoir sampling picks k items
reservoir-sampling
streaming
randomness
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/streaming-running-averages-in-typescript-explained-typescript-582d/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.