Skip to the solution
MediumFrontend9 min read

What are pipes in Angular?

311 views

The problem

Question presented to candidate: "What are pipes in Angular? Show me how you would use a built-in one, write a custom one, and explain what pure: false changes."

What a strong answer should cover:

  • A pipe is a class with @Pipe({ name }) and a transform(value, ...args) method, used in templates as {{ value | name: arg }} to format or derive a value for display.
  • Built-ins from @angular/common: date, currency, decimal, percent, uppercase, lowercase, titlecase, json, slice, keyvalue, async, and the i18n pipes; pipes chain left to right.
  • Pipes are standalone and must be imported into the component that uses them.
  • Pure pipes (the default) re-run only when an input changes by reference or primitive value, so they are cheap; mutating an array or object does not re-run them.
  • Impure pipes (pure: false) run on every change detection pass of the view, so they see mutations but cost more; async is the famous impure built-in.
  • Compared to calling a method in the template, a pure pipe memoises on its inputs; computed() is the signal-era alternative for component-level derived state.

Clarifying questions expected:

  • "Is the data immutable, or do we mutate arrays in place?"

Code / implementation expected: Yes β€” a custom pipe with an argument, used in a template.

  • pipes

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 10 sections

Read the code

AngularBuilt-in pipes, a custom pure pipe with an argument, and an impure twin that logs every call
import { Component, Pipe, PipeTransform, signal } from "@angular/core";
import { CurrencyPipe, DatePipe, UpperCasePipe } from "@angular/common";

// A custom pure pipe with an argument: {{ cart | total: 0.2 }}
@Pipe({ name: "total" })
export class TotalPipe implements PipeTransform {
  transform(prices: number[], taxRate = 0): number {
    console.log("pure   total(" + prices.length + " items)");
    return prices.reduce((sum, p) => sum + p, 0) * (1 + taxRate);
  }
}

// Same logic, but impure: re-runs on every change detection pass of this view.
@Pipe({ name: "totalImpure", pure: false })
export class TotalImpurePipe implements PipeTransform {
  transform(prices: number[], taxRate = 0): number {
    console.log("impure total(" + prices.length + " items)");
    return prices.reduce((sum, p) => sum + p, 0) * (1 + taxRate);
  }
}

@Component({
  selector: "app-root",
  imports: [TotalPipe, TotalImpurePipe, CurrencyPipe, DatePipe, UpperCasePipe],
  template: `
    <p>{{ "order summary" | uppercase }} for {{ placed | date: "d MMM y" }}</p>
    <p id="pure">Pure: {{ cart | total: 0.2 | currency: "EUR" }}</p>
    <p id="impure">Impure: {{ cart | totalImpure: 0.2 | currency: "EUR" }}</p>
    <p>Clicks: {{ clicks() }}</p>

    <button (click)="clicks.set(clicks() + 1)">Unrelated change</button>
    <button (click)="cart.push(10)">Add item (mutate)</button>
    <button (click)="cart = [...cart, 10]">Add item (new array)</button>
  `,
})
export class AppComponent {
  cart = [25, 15];
  clicks = signal(0);
  placed = new Date(2026, 9, 16);
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 71 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextMedium

What is the difference between providing a service in root vs in a component?

Continue