prefer-switch-expression

Group
Style
Path
lint/style/prefer-switch-expression
Default
Off, opt in
Origin
Falcon
Rule
409 of 512

Prefer switch expressions for exhaustive switches that only return or assign a value.

A switch expression makes value selection explicit without repeating return or the assignment target. This rule flags Dart 3 switches whose branches are all a single value-returning return, or all a plain = assignment to the same simple identifier, optionally followed by an unlabeled break. Single throw branches may accompany either form.

A default or unguarded, untyped wildcard case is required: exhaustiveness is not inferred from types. Grouped/fallthrough cases, labeled cases, empty bodies, blocks, extra statements, mixed return/assignment branches, compound assignments, property/index targets, and labeled breaks are excluded. Assignment patterns binding the target name are excluded, since equal target spellings need not refer to the same variable across branches. No automatic fix is offered.

Invalid

example.dartdart
String describe(int value) {
  switch (value) {
    case 1:
      return 'one';
    default:
      return 'other';
  }
}

int absolute(int value) {
  switch (value) {
    case < 0:
      return -value;
    case _:
      return value;
  }
}

int guarded(Object value) {
  switch (value) {
    case int number when number > 0:
      return number;
    default:
      return 0;
  }
}

int select(int value) {
  var result = 0;
  switch (value) {
    case 1:
      result = 10;
      break;
    default:
      result = 20;
      break;
  }
  return result;
}

String choose(bool value) {
  var result = '';
  switch (value) {
    case true:
      result = 'yes';
      break;
    case _:
      result = 'no';
      break;
  }
  return result;
}

Future<int> asynchronous(int value) async {
  switch (value) {
    case 1:
      return await Future.value(1);
    default:
      return await Future.value(0);
  }
}

int implicitBreak(int value) {
  var result = 0;
  switch (value) {
    case 1:
      result = 1;
    default:
      result = 2;
  }
  return result;
}

int independentBinding(Object value) {
  var result = 0;
  switch (value) {
    case int number:
      result = number;
    default:
      result = -1;
      break;
  }
  return result;
}

int returningWithThrow(int value) {
  switch (value) {
    case 1:
      return 1;
    default:
      throw StateError('Unsupported value');
  }
}

int assigningWithThrow(int value) {
  var result = 0;
  switch (value) {
    case 0:
      throw StateError('Zero');
    case 1:
      result = 1;
      break;
    default:
      result = 2;
  }
  return result;
}
Use a switch expression to select this value.
1String describe(int value) {
2 switch (value) {
Use a switch expression to select this value.
10int absolute(int value) {
11 switch (value) {
Use a switch expression to select this value.
19int guarded(Object value) {
20 switch (value) {
Use a switch expression to select this value.
29 var result = 0;
30 switch (value) {
Use a switch expression to select this value.
42 var result = '';
43 switch (value) {
Use a switch expression to select this value.
54Future<int> asynchronous(int value) async {
55 switch (value) {
Use a switch expression to select this value.
64 var result = 0;
65 switch (value) {
Use a switch expression to select this value.
75 var result = 0;
76 switch (value) {
Use a switch expression to select this value.
86int returningWithThrow(int value) {
87 switch (value) {
Use a switch expression to select this value.
96 var result = 0;
97 switch (value) {

Valid

example.dartdart
String expression(int value) => switch (value) {
  1 => 'one',
  _ => 'other',
};

// Even if a type could prove exhaustiveness, this rule requires a fallback.
int noFallback(bool value) {
  switch (value) {
    case true:
      return 1;
    case false:
      return 0;
  }
}

int grouped(int value) {
  switch (value) {
    case 1:
    case 2:
      return 1;
    default:
      return 0;
  }
}

void empty(int value) {
  switch (value) {
    case 1:
      break;
    default:
  }
}

int extraWork(int value) {
  switch (value) {
    case 1:
      print(value);
      return 1;
    default:
      return 0;
  }
}

void noValues(int value) {
  switch (value) {
    case 1:
      return;
    default:
      return;
  }
}

int differentTargets(int value) {
  var first = 0;
  var second = 0;
  switch (value) {
    case 1:
      first = 1;
      break;
    default:
      second = 2;
      break;
  }
  return first + second;
}

int compound(int value) {
  var result = 0;
  switch (value) {
    case 1:
      result += 1;
      break;
    default:
      result += 2;
      break;
  }
  return result;
}

class Box {
  int value = 0;
}

void properties(int value, Box box) {
  switch (value) {
    case 1:
      box.value = 1;
      break;
    default:
      box.value = 2;
      break;
  }
}

void indexed(int value, List<int> values) {
  switch (value) {
    case 1:
      values[0] = 1;
      break;
    default:
      values[0] = 2;
      break;
  }
}

int mixed(int value) {
  var result = 0;
  switch (value) {
    case 1:
      return 1;
    default:
      result = 2;
      break;
  }
  return result;
}

int blocks(int value) {
  switch (value) {
    case 1:
      { return 1; }
    default:
      { return 0; }
  }
}

int labeledBreak(int value) {
  var result = 0;
  outer: while (true) {
    switch (value) {
      case 1:
        result = 1;
        break outer;
      default:
        result = 2;
        break outer;
    }
  }
  return result;
}

int labeledCase(int value) {
  switch (value) {
    target: case 1:
      return 1;
    default:
      return 0;
  }
}

int guardedWildcard(int value) {
  switch (value) {
    case _ when value > 0:
      return 1;
    case 0:
      return 0;
  }
  return -1;
}

int typedWildcard(Object value) {
  switch (value) {
    case int _:
      return 1;
    case String _:
      return 2;
  }
  return 0;
}

// Same spelling does not imply the same variable in different patterns.
int patternBinding(Object value) {
  var result = 0;
  switch (value) {
    case int result:
      result = 1;
      break;
    default:
      result = 2;
      break;
  }
  return result;
}

Never onlyThrows(int value) {
  switch (value) {
    case 1:
      throw StateError('One');
    default:
      throw StateError('Other');
  }
}

int throwWithExtraStatement(int value) {
  switch (value) {
    case 1:
      print(value);
      throw StateError('One');
    default:
      return 0;
  }
}

int implicitAssignmentWithExtraStatement(int value) {
  var result = 0;
  switch (value) {
    case 1:
      result = 1;
      print(result);
    default:
      result = 2;
  }
  return result;
}

Configure prefer-switch-expression

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-switch-expression": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/prefer-switch-expression: <reason>