Templates
Pipes: pure, impure & async
Transforming values, the pure/impure performance trade-off, and the async pipe.
A pipe transforms a value for display via a transform method. Pure pipes (the default) recompute only when the input reference changes, so they are cheap and cached across change-detection cycles.
A pure pipe is a cached calculation stapled to its inputs; an impure pipe is a meter that re-reads on every tick whether or not anything changed.
Key concepts
1
An impure pipe (pure: false) runs on every cycle — necessary for things like filtering a mutable array, but a common performance trap. Prefer precomputing derived data in the component over an impure filter pipe.
impure pipepure: false
2
The async pipe subscribes to an observable/promise, returns the latest value, and unsubscribes automatically on destroy — the idiomatic way to render streams without leaks.
`async` pipeunsubscribes automaticallyasync
3
Pitfall: mutating an array in place will not trigger a pure pipe; return a new array. Interview follow-up: "why can filtering with an impure pipe hurt performance?" — it re-runs for every item on every CD tick.
Pitfall:Interview follow-up:
typescript
@Pipe({ name: 'timeAgo', standalone: true, pure: true })
export class TimeAgoPipe implements PipeTransform {
transform(value: Date | string): string {
const secs = Math.floor((Date.now() - new Date(value).getTime()) / 1000);
if (secs < 60) return 'just now';
if (secs < 3600) return `${Math.floor(secs / 60)}m ago`;
return `${Math.floor(secs / 3600)}h ago`;
}
}
// template: {{ post.createdAt | timeAgo }} — {{ user$ | async }}