prefer-iterable-where-type

Same as prefer_iterable_whereType in Dart lints

Group
Style
Path
lint/style/prefer-iterable-where-type
Default
On (recommended)
Origin
Dart lints
Rule
382 of 512
recommended

Flags .where((e) => e is T), which .whereType<T>() expresses directly.

Filtering an iterable with an is test is exactly what Iterable.whereType does, but the method also narrows the element type, yielding an Iterable<T> instead of leaving the original element type in place. Using whereType<T>() is shorter, avoids the throwaway closure, and removes the casts or checks that a bare where filter would still require downstream. The rule matches a .where call carrying exactly one positional argument and no named arguments, where that argument is a one-parameter arrow closure of the form param is T — the test must be non-negated and applied to the closure's own parameter.

Semantic analysis requires declaration identities. Once available, an unknown receiver still triggers the lint. A TypeIndex can suppress it only when the receiver is proven not to be an Iterable and to have no whereType member; source-resolved members and subtypes take precedence. A user type carrying its own whereType keeps firing. Without a type index, negative proofs are unavailable, but source-derived types are still inferred.

Invalid

example.dartdart
void bad() {
  var a = items.where((e) => e is String);
  var b = list.where((x) => x is int);
  var c = things.where((t) => t is Widget);
  var d = values.where((v) => v is double).toList();
  var e = data.where((item) => item is Map);
}

// A `List` receiver IS an Iterable (`is_subtype(List, Iterable)` is `Yes`, not
// `ProvenNo`), so `whereType<T>()` applies and the diagnostic keeps firing even
// with type knowledge attached.
void iterableReceiver(List<int> xs) {
  xs.where((e) => e is int);
}

// `Custom` is not an Iterable, but it carries its own `whereType` — so
// `member_lookup` is `Found`, never `ProvenAbsent`, and the rewrite is valid.
// The diagnostic keeps firing (type knowledge suppresses only on positive proof
// that `whereType` is absent).
class Custom {
  Custom where(bool Function(dynamic) test) => this;
  Iterable<T> whereType<T>() => throw '';

  void run() {
    this.where((e) => e is String);
  }
}
Use `whereType<T>()` instead of `where` with an `is` check.
1void bad() {
2 var a = items.where((e) => e is String);
Use `whereType<T>()` instead of `where` with an `is` check.
2 var a = items.where((e) => e is String);
3 var b = list.where((x) => x is int);
Use `whereType<T>()` instead of `where` with an `is` check.
3 var b = list.where((x) => x is int);
4 var c = things.where((t) => t is Widget);
Use `whereType<T>()` instead of `where` with an `is` check.
4 var c = things.where((t) => t is Widget);
5 var d = values.where((v) => v is double).toList();
Use `whereType<T>()` instead of `where` with an `is` check.
5 var d = values.where((v) => v is double).toList();
6 var e = data.where((item) => item is Map);
Use `whereType<T>()` instead of `where` with an `is` check.
12void iterableReceiver(List<int> xs) {
13 xs.where((e) => e is int);
Use `whereType<T>()` instead of `where` with an `is` check.
24 void run() {
25 this.where((e) => e is String);

Valid

example.dartdart
void good() {
  var a = items.whereType<String>();
  var b = list.where((e) => e.isValid);
  var c = things.where((e) => e is! String);
  var d = values.where((e) => e is int && e > 0);
  var e = data.where((a, b) => a is int);
  var f = items.map((e) => e is String);
}

// `Query` is not an Iterable and has no `whereType` member, so `.whereType<T>()`
// does not exist on it: `.where((e) => e is T)` here is SUPPRESSED because the
// receiver type is positively proven. This holds for a typed parameter, for
// `this`, and for a constructor-call receiver.
// (Requires the corpus harness to attach a TypeIndex for this rule; without one
// the receiver is Unknown and these lines would fire.)
class Query {
  Query where(bool Function(dynamic) test) => this;

  void run(Query q) {
    q.where((e) => e is String);
    this.where((e) => e is int);
    Query().where((e) => e is num);
  }
}

Configure prefer-iterable-where-type

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-iterable-where-type": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/prefer-iterable-where-type: <reason>