test-types-in-equals

Same as test_types_in_equals in Dart lints

Path
lint/correctness/test-types-in-equals
Default
On (recommended)
Origin
Dart lints
Rule
440 of 512
recommended

Flags casting the parameter of operator == instead of testing its type.

== must accept any object and answer false for unrelated types. Casting the parameter with as throws a CastError for those instead, so comparing with an object of another type crashes. Test the type with is (or a pattern) and return false when it does not match.

class Field {
  @override
  bool operator ==(Object other) {
    Field otherField = other as Field;  // flagged
    return value == otherField.value;
  }
}

Invalid

example.dartdart
class Field {
  final int value;
  Field(this.value);

  @override
  bool operator ==(Object other) {
    Field otherField = other as Field;
    return value == otherField.value;
  }

  @override
  int get hashCode => value.hashCode;
}

class Pair {
  final int a;
  Pair(this.a);

  @override
  bool operator ==(Object other) => (other as Pair).a == a;

  @override
  int get hashCode => a;
}

class Named {
  final String name;
  Named(this.name);

  @override
  bool operator ==(Object o) =>
      identical(this, o) || (o as Named).name == name;

  @override
  int get hashCode => name.hashCode;
}

enum Color {
  red;

  bool same(Object other) => true;
}

mixin Comparable2 {
  int get key;

  @override
  bool operator ==(Object other) => key == (other as Comparable2).key;

  @override
  int get hashCode => key;
}

class Twice {
  final int x;
  Twice(this.x);

  @override
  bool operator ==(Object other) {
    final a = other as Twice;
    final b = other as dynamic;
    return a.x == b.x;
  }

  @override
  int get hashCode => x;
}
Add a type test for `Field` in `==`.
6 bool operator ==(Object other) {
7 Field otherField = other as Field;
Add a type test for `Pair` in `==`.
19 @override
20 bool operator ==(Object other) => (other as Pair).a == a;
Add a type test for `Named` in `==`.
31 bool operator ==(Object o) =>
32 identical(this, o) || (o as Named).name == name;
Add a type test for `Comparable2` in `==`.
47 @override
48 bool operator ==(Object other) => key == (other as Comparable2).key;
Add a type test for `Twice` in `==`.
59 bool operator ==(Object other) {
60 final a = other as Twice;
Add a type test for `Twice` in `==`.
60 final a = other as Twice;
61 final b = other as dynamic;

Valid

example.dartdart
class Field {
  final int value;
  Field(this.value);

  @override
  bool operator ==(Object other) {
    if (other is! Field) return false;
    return value == other.value;
  }

  @override
  int get hashCode => value.hashCode;
}

class Pair {
  final int a;
  Pair(this.a);

  @override
  bool operator ==(Object other) => other is Pair && other.a == a;

  @override
  int get hashCode => a;
}

// Pattern-based type test.
class Point {
  final int x;
  Point(this.x);

  @override
  bool operator ==(Object other) => switch (other) {
        Point(:final x) => x == this.x,
        _ => false,
      };

  @override
  int get hashCode => x;
}

// Casting something other than the parameter.
class Holder {
  final Object inner;
  Holder(this.inner);

  @override
  bool operator ==(Object other) =>
      other is Holder && (inner as num) == (other.inner as num);

  @override
  int get hashCode => inner.hashCode;
}

// Casts in ordinary methods are not reported.
class Util {
  bool equals(Object other) => (other as Util) == this;
}

Configure test-types-in-equals

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "test-types-in-equals": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/correctness/test-types-in-equals: <reason>