Angular @Pipe Without PipeTransform

ID

javascript.angular_pipe_transform_interface

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

angular, framework, reliability, types

Description

Reports an Angular @Pipe class that does not declare implements PipeTransform:

// Bad — nothing checks the method below.
@Pipe({ name: "shorten", standalone: true })
export class ShortenPipe {
  tranform(value: string): string {     // typo; throws at render time
    return value.slice(0, 10);
  }
}

// Good
@Pipe({ name: "shorten", standalone: true })
export class ShortenPipe implements PipeTransform {
  transform(value: string): string {
    return value.slice(0, 10);
  }
}

Rationale

A pipe is called by name from a template, so its contract is never checked at the call site — {{ value | shorten }} compiles whatever the class happens to contain.

The one place the contract can be checked is the class itself, and PipeTransform is the declaration that asks for that check: it makes the compiler verify that a transform method exists and has a usable signature.

Without it, a misspelled method name, a missing method, or a transform that does not take the piped value all compile cleanly and fail at render time — inside a template, with no line pointing back at the pipe.

Remediation

Declare the interface:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({ name: "shorten", standalone: true })
export class ShortenPipe implements PipeTransform {
  transform(value: string, max = 10): string {
    return value.slice(0, max);
  }
}

Notes

A pipe that extends another class is left alone: the base may itself be a pipe that declares the interface, and this rule reads one class at a time.

javascript.angular_lifecycle_interface makes the same argument for the eight ng* lifecycle hooks. It maps only those, so the pipe contract needs its own rule.

© 2026 Xygeni. All rights reserved