typescript 47 lines · 8 steps

Building a cached money pipe in Angular

A standalone Angular pipe that formats currency with Intl.NumberFormat and memoizes formatters by locale and options.

Explained by highlit
1import { Pipe, PipeTransform, Inject, LOCALE_ID } from '@angular/core';
2 
3interface MoneyOptions {
4 currency?: string;
5 display?: 'symbol' | 'code' | 'name';
6 minimumFractionDigits?: number;
7}
8 
9@Pipe({
10 name: 'money',
11 standalone: true,
12})
13export class MoneyPipe implements PipeTransform {
14 private readonly formatters = new Map<string, Intl.NumberFormat>();
15 
16 constructor(@Inject(LOCALE_ID) private readonly locale: string) {}
17 
18 transform(
19 value: number | string | null | undefined,
20 options: MoneyOptions = {},
21 ): string {
22 if (value == null || value === '') {
23 return '';
24 }
25 
26 const amount = typeof value === 'string' ? Number(value) : value;
27 if (Number.isNaN(amount)) {
28 return '';
29 }
30 
31 const { currency = 'USD', display = 'symbol', minimumFractionDigits } = options;
32 const cacheKey = `${this.locale}|${currency}|${display}|${minimumFractionDigits ?? ''}`;
33 
34 let formatter = this.formatters.get(cacheKey);
35 if (!formatter) {
36 formatter = new Intl.NumberFormat(this.locale, {
37 style: 'currency',
38 currency,
39 currencyDisplay: display,
40 minimumFractionDigits,
41 });
42 this.formatters.set(cacheKey, formatter);
43 }
44 
45 return formatter.format(amount);
46 }
47}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Caching expensive-to-construct objects like Intl.NumberFormat by a composite key avoids rebuilding them on every change-detection pass.
  2. 2Guarding against null, empty, and NaN inputs keeps a pipe safe to bind directly to raw template data.
  3. 3Injecting LOCALE_ID lets formatting follow the app's configured locale instead of a hardcoded default.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a cached money pipe in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code