Why is this an issue?

A type guard is a TypeScript feature that allows you to narrow the type of a variable within a conditional block of code. It is a way to tell the TypeScript compiler that an expression is of a certain type, based on some condition that you check at runtime.

function printLength(x: any) {
  if (typeof x === 'string') {
    console.log(x.length);
  }
}

Type predicates are user-defined functions that work as type guards, where you define yourself how to narrow the type of an expression based on some custom condition. These are just functions with a return type of argumentName is SomeType. Such functions return true if the argument is of the specified type.

function isString(x: any): x is string {
  return typeof x === 'string';
}

function printLength(x: any) {
  if (isString(x)) {
    console.log(x.length);
  }
}

One of the advantages of using such a function is that in a conditional block where the condition is a type guard, the compiler automatically performs the appropriate casts, so explicit casting becomes unnecessary.

Type predicates provide a more precise, readable, and flexible way to check types in your code, which can lead to more robust and maintainable code.

This rule raises an issue when a boolean function checking for the type of its only argument can be replaced with a type predicate.

function isSomething(x: BaseType): boolean { // Noncompliant
  return (<Something>x).foo !== undefined;
}

if (isSomething(v)) {
  (<Something>v).foo();
  (v as Something).foo();
}

Transform the function into a type predicate, adding a return type annotation that specifies the type predicate.

function isSomething(x: BaseType): x is Something {
  return (<Something>x).foo !== undefined;
}

if (isSomething(v)) {
  v.foo();
}

Resources

Documentation