avoid-unrelated-type-assertions

Same as avoid-unrelated-type-assertions in Dart Code Metrics

Path
lint/suspicious/avoid-unrelated-type-assertions
Default
On (recommended)
Origin
Dart Code Metrics
Rule
178 of 512
recommended

Flags an is check proven impossible by canonical resolved types.

Invalid

example.dartdart
// Test cases for avoid-unrelated-type-assertions rule
// Flags 'is T' checks that are structurally impossible

void testStringIsInt() {
  if ("hello" is int) {
    print("string is int");
  }
}

void testIntIsString() {
  if (42 is String) {
    print("int is string");
  }
}

void testDoubleIsBool() {
  if (3.14 is bool) {
    print("double is bool");
  }
}

void testListIsMap() {
  if ([1, 2, 3] is Map) {
    print("list is map");
  }
}

void testMultipleImpossibleAssertions() {
  final x = "test";
  final y = 42;
  final z = true;

  if (x is int) {
    print("x is int");
  }

  if (y is String) {
    print("y is string");
  }

  if (z is List) {
    print("z is list");
  }
}

void testStringIsMapType() {
  if ("value" is Map<String, int>) {
    print("string is map");
  }
}

void testConditionalExpressionImpossible() {
  final result = "text" is int ? "yes" : "no";
}

void testOldStyleFunctionFormal(String callback()) {
  if (callback is String) {
    print("function is string");
  }
}

void testForInBindings() {
  for (final value in <String>['x']) {
    if (value is int) {
      print("string is int");
    }
  }
  for (String value in <String>['x']) {
    if (value is int) {
      print("string is int");
    }
  }
  for (final [value] in <List<String>>[
    ['x'],
  ]) {
    if (value is int) {
      print("string is int");
    }
  }
}

class ConstructorInitializerCheck {
  final bool impossible;

  ConstructorInitializerCheck()
      : impossible = "text" is int;
}

// Regression: the violation must still be found inside Dart 3 containers
// (pattern declaration, labeled statement, switch expression and subject,
// collection if/spread, record field).
void containersRegression(int rcount) {
  final (ra, _) = ("hello" is int, 0);
  lbl: {
    final rb = "hello" is int;
    print(rb);
  }
  final rc = switch (rcount) {
    0 => "hello" is int,
    _ => null,
  };
  final rd = switch ("hello" is int) {
    _ => 0,
  };
  final re = [if (rcount > 0) "hello" is int];
  final rf = [...["hello" is int]];
  final rg = (p: "hello" is int, q: 0);
  print([ra, rc, rd, re, rf, rg]);
}
Remove this type assertion because the types are unrelated and it can never be true.
4void testStringIsInt() {
5 if ("hello" is int) {
Remove this type assertion because the types are unrelated and it can never be true.
10void testIntIsString() {
11 if (42 is String) {
Remove this type assertion because the types are unrelated and it can never be true.
16void testDoubleIsBool() {
17 if (3.14 is bool) {
Remove this type assertion because the types are unrelated and it can never be true.
22void testListIsMap() {
23 if ([1, 2, 3] is Map) {
Remove this type assertion because the types are unrelated and it can never be true.
32
33 if (x is int) {
Remove this type assertion because the types are unrelated and it can never be true.
36
37 if (y is String) {
Remove this type assertion because the types are unrelated and it can never be true.
40
41 if (z is List) {
Remove this type assertion because the types are unrelated and it can never be true.
46void testStringIsMapType() {
47 if ("value" is Map<String, int>) {
Remove this type assertion because the types are unrelated and it can never be true.
52void testConditionalExpressionImpossible() {
53 final result = "text" is int ? "yes" : "no";
Remove this type assertion because the types are unrelated and it can never be true.
56void testOldStyleFunctionFormal(String callback()) {
57 if (callback is String) {
Remove this type assertion because the types are unrelated and it can never be true.
63 for (final value in <String>['x']) {
64 if (value is int) {
Remove this type assertion because the types are unrelated and it can never be true.
68 for (String value in <String>['x']) {
69 if (value is int) {
Remove this type assertion because the types are unrelated and it can never be true.
75 ]) {
76 if (value is int) {
Remove this type assertion because the types are unrelated and it can never be true.
85 ConstructorInitializerCheck()
86 : impossible = "text" is int;
Remove this type assertion because the types are unrelated and it can never be true.
92void containersRegression(int rcount) {
93 final (ra, _) = ("hello" is int, 0);
Remove this type assertion because the types are unrelated and it can never be true.
94 lbl: {
95 final rb = "hello" is int;
Remove this type assertion because the types are unrelated and it can never be true.
98 final rc = switch (rcount) {
99 0 => "hello" is int,
Remove this type assertion because the types are unrelated and it can never be true.
101 };
102 final rd = switch ("hello" is int) {
Remove this type assertion because the types are unrelated and it can never be true.
104 };
105 final re = [if (rcount > 0) "hello" is int];
Remove this type assertion because the types are unrelated and it can never be true.
105 final re = [if (rcount > 0) "hello" is int];
106 final rf = [...["hello" is int]];
Remove this type assertion because the types are unrelated and it can never be true.
106 final rf = [...["hello" is int]];
107 final rg = (p: "hello" is int, q: 0);

Valid

example.dartdart
// Good examples for avoid-unrelated-type-assertions rule
// Type checks where the assertion is possible or plausible

void testDynamicTypeCheck() {
  dynamic value = "hello";
  if (value is String) {
    print("value is string");
  }
}

void testObjectTypeCheck() {
  Object obj = 42;
  if (obj is int) {
    print("obj is int");
  }
}

void testValidTypeCheckWithParameter() {
  void checkType(dynamic param) {
    if (param is String) {
      print("param is string");
    }
  }
}

void testValidListTypeCheck() {
  dynamic data = [1, 2, 3];
  if (data is List) {
    print("data is list");
  }
}

void testValidMapTypeCheck() {
  dynamic config = {"key": "value"};
  if (config is Map) {
    print("config is map");
  }
}

void testValidNullableTypeCheck() {
  Object? value = "text";
  if (value is String) {
    print("value is string");
  }
}

void testValidUnionLikeType() {
  Object data = 42;
  if (data is int || data is String) {
    print("data is int or string");
  }
}

class T {}

mixin M<T> {
  bool unrelatedTypeParameterCheck(T value) => value is int;
}

Configure avoid-unrelated-type-assertions

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "avoid-unrelated-type-assertions": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/suspicious/avoid-unrelated-type-assertions: <reason>