typescript 34 lines · 7 steps

A memoized chunk pipe in Angular

An Angular pipe that splits an array into fixed-size groups and caches results with a WeakMap to stay change-detection friendly.

Explained by highlit
1import { Pipe, PipeTransform } from '@angular/core';
2 
3@Pipe({
4 name: 'chunk',
5 standalone: true,
6})
7export class ChunkPipe implements PipeTransform {
8 private cache = new WeakMap<readonly unknown[], Map<number, unknown[][]>>();
9 
10 transform<T>(items: readonly T[] | null | undefined, size: number): T[][] {
11 if (!items?.length || size < 1) {
12 return [];
13 }
14 
15 let bySize = this.cache.get(items);
16 if (!bySize) {
17 bySize = new Map();
18 this.cache.set(items, bySize);
19 }
20 
21 const cached = bySize.get(size);
22 if (cached) {
23 return cached as T[][];
24 }
25 
26 const chunks: T[][] = [];
27 for (let i = 0; i < items.length; i += size) {
28 chunks.push(items.slice(i, i + size));
29 }
30 
31 bySize.set(size, chunks);
32 return chunks;
33 }
34}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Pure pipes run on every change detection, so caching by reference identity keeps them cheap.
  2. 2A WeakMap keyed on the input array lets cached results be garbage-collected when the array goes away.
  3. 3Returning the same cached array reference avoids breaking downstream reference-based change detection.

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
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
javascript
import { useState, useEffect, useCallback, useRef } from 'react';
 
const cache = new Map();
const inflight = new Map();

Building a stale-while-revalidate hook in React

caching request-deduplication custom-hooks
Advanced 10 steps
php
<?php
 
namespace App\Services;
 

Building a cached daily leaderboard in Laravel

caching aggregation eager-loading
Intermediate 9 steps

Share this explainer

Here's the card — post it anywhere.

A memoized chunk pipe in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code