avoid-unnecessary-type-assertions

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

Path
lint/complexity/avoid-unnecessary-type-assertions
Default
On (recommended)
Origin
Dart Code Metrics
Rule
175 of 512
recommended

Flags an is check whose result is already guaranteed by the resolved static type.

Invalid

example.dartdart
// Test cases for avoid-unnecessary-type-assertions rule
// Flags 'is T' checks where the variable is already known to be T

void testExplicitIntType() {
  final int x = 5;
  if (x is int) {
    print("x is int");
  }
}

void testExplicitStringType() {
  final String name = "hello";
  if (name is String) {
    print("name is string");
  }
}

void testExplicitListType() {
  final List<String> items = [];
  if (items is List) {
    print("items is list");
  }
}

void testMultipleUnnecessaryAssertions() {
  final bool active = true;
  final double value = 3.14;

  if (active is bool) {
    print("active is bool");
  }

  if (value is double) {
    print("value is double");
  }
}

class MyClass {
  final int id = 42;

  void checkId() {
    if (id is int) {
      print("id is int");
    }
  }
}

void testInlineAssertion() {
  final String message = "test";
  final result = message is String ? "yes" : "no";
}

// Regression: a nested block inherits the enclosing declarations, so a
// redundant assertion inside one is still recognised.
void nestedScopeRegression() {
  final int known = 1;
  {
    final inBlock = known is int;
    print(inBlock);
  }
  lbl: {
    final inLabeled = known is int;
    print(inLabeled);
  }
}

// Regression: try/catch/finally bodies also inherit the enclosing
// declarations, the same way a plain nested block does.
void tryScopeRegression() {
  final int known = 1;
  try {
    print(known is int);
  } catch (e) {
    print(known is int);
  } finally {
    print(known is int);
  }
}

void typedCollectionForAssertionRegression() {
  final list = [
    for (int i = 0; i < 2; i++) i is int,
  ];
  final map = {
    for (int j = 0; j < 2; j++) j: j is int,
  };
  print([list, map]);
}

// Initializing an `int?` local with an `int` promotes it to `int`; Dart 3.13.5
// `dart analyze` reports unnecessary_type_check here.
void testCheckPromotedOnInitialization() {
  int? maybeInt = 5;
  if (maybeInt is int) {
    print("maybeInt is int");
  }
}
Remove this type assertion because the variable is already known to have this type.
5 final int x = 5;
6 if (x is int) {
Remove this type assertion because the variable is already known to have this type.
12 final String name = "hello";
13 if (name is String) {
Remove this type assertion because the variable is already known to have this type.
19 final List<String> items = [];
20 if (items is List) {
Remove this type assertion because the variable is already known to have this type.
28
29 if (active is bool) {
Remove this type assertion because the variable is already known to have this type.
32
33 if (value is double) {
Remove this type assertion because the variable is already known to have this type.
41 void checkId() {
42 if (id is int) {
Remove this type assertion because the variable is already known to have this type.
49 final String message = "test";
50 final result = message is String ? "yes" : "no";
Remove this type assertion because the variable is already known to have this type.
57 {
58 final inBlock = known is int;
Remove this type assertion because the variable is already known to have this type.
61 lbl: {
62 final inLabeled = known is int;
Remove this type assertion because the variable is already known to have this type.
71 try {
72 print(known is int);
Remove this type assertion because the variable is already known to have this type.
73 } catch (e) {
74 print(known is int);
Remove this type assertion because the variable is already known to have this type.
75 } finally {
76 print(known is int);
Remove this type assertion because the variable is already known to have this type.
81 final list = [
82 for (int i = 0; i < 2; i++) i is int,
Remove this type assertion because the variable is already known to have this type.
84 final map = {
85 for (int j = 0; j < 2; j++) j: j is int,
Remove this type assertion because the variable is already known to have this type.
93 int? maybeInt = 5;
94 if (maybeInt is int) {

Valid

example.dartdart
// Good examples for avoid-unnecessary-type-assertions rule
// Type checks where the type is not already known

void testDynamicTypeCheck() {
  dynamic value = 42;
  if (value is int) {
    print("value is int");
  }
}

void testObjectTypeCheck() {
  Object obj = "hello";
  if (obj is String) {
    print("obj is string");
  }
}

void testParameterTypeCheck() {
  void checkType(dynamic param) {
    if (param is bool) {
      print("param is bool");
    }
  }
}

void testNullableTypeCheck() {
  int? maybeInt = int.tryParse('5');
  if (maybeInt is int) {
    print("maybeInt is int");
  }
}

void testBroadTypeCheck() {
  List<dynamic> items = [];
  if (items is List<String>) {
    print("items is List<String>");
  }
}

void testInheritanceTypeCheck() {
  Object shape = Circle();
  if (shape is Circle) {
    print("shape is Circle");
  }
}

class Circle {}

Configure avoid-unnecessary-type-assertions

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "complexity": {
        "avoid-unnecessary-type-assertions": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/complexity/avoid-unnecessary-type-assertions: <reason>
  • avoid-unnecessary-type-castsavoid-unnecessary-type-castsrecommended

    Flags an as cast to the operand's resolved static type.

  • cascade-invocationscascade_invocations

    Flags consecutive statements that invoke members on the same variable.

  • cognitive-complexity

    Reports function bodies with excessive nesting-weighted control flow.

  • cyclomatic-complexitycyclomatic_complexity

    Flags a function whose cyclomatic complexity exceeds the configured threshold.

  • join-return-with-assignmentjoin_return_with_assignment

    Flags an assignment immediately followed by return of the same variable.

  • max-lines-for-filemax_lines_for_file

    Flags a file longer than the configured line limit.

  • max-lines-for-functionmax_lines_for_function

    Flags a function or method longer than the configured line limit.

  • max-parameters-for-functionmax_parameters_for_function

    Flags callable declarations and function types with more than the configured number of parameters.