unnecessary-final

Same as unnecessary_final in Dart lints

Group
Style
Path
lint/style/unnecessary-final
Default
Off, opt in
Origin
Dart lints
Rule
454 of 512

Don't use final for local variables and parameters.

Some codebases prefer var for locals and plain parameters, reserving final for fields and top-level declarations. This flags the final keyword on parameters, local variable statements, for-each loop variables of for statements (including destructuring loops), pattern variable declarations, and variable patterns (case final x). C-style for initializers are not variable declaration statements and are left alone; neither are collection for elements ([for (final x in xs) x]), which the analyzer does not visit. Parameters are checked only before Dart 3.13: with primary constructors a parameter's final declares a field instead. Local keyword spans come from the syntax tree, not matching words in documentation or annotation arguments.

void f(final int x) { // flagged
  final y = x + 1; // flagged
  var z = y; // ok
}

Invalid

example.dartdart
// @dart = 3.12

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

void params(final int x, {final String? name}) {
  final y = x + 1;
  final int z = y;
  print('$z$name');
}

void loops(List<int> numbers, List<(int, int)> rows) {
  for (final n in numbers) {
    print(n);
  }
  for (final (a, b) in rows) {
    print(a + b);
  }
  final (c, d) = rows.first;
  print(c + d);
}

void cases(Object o) {
  if (o case final int value) {
    print(value);
  }
  switch (o) {
    case Pair(a: final first):
      print(first);
  }
  final handler = (final int v) => v;
  print(handler);
}

void functionTyped(List<void Function(String message)> listeners) {
  for (final void Function(String message) listener in listeners) {
    listener('x');
  }
}
Local variables should not be marked as `final`.
7
8void params(final int x, {final String? name}) {
Local variables should not be marked as `final`.
7
8void params(final int x, {final String? name}) {
Local variables should not be marked as `final`.
8void params(final int x, {final String? name}) {
9 final y = x + 1;
Local variables should not be marked as `final`.
9 final y = x + 1;
10 final int z = y;
Local variables should not be marked as `final`.
14void loops(List<int> numbers, List<(int, int)> rows) {
15 for (final n in numbers) {
Local variables should not be marked as `final`.
17 }
18 for (final (a, b) in rows) {
Local variables should not be marked as `final`.
20 }
21 final (c, d) = rows.first;
Local variables should not be marked as `final`.
25void cases(Object o) {
26 if (o case final int value) {
Local variables should not be marked as `final`.
29 switch (o) {
30 case Pair(a: final first):
Local variables should not be marked as `final`.
32 }
33 final handler = (final int v) => v;
Local variables should not be marked as `final`.
32 }
33 final handler = (final int v) => v;
Local variables should not be marked as `final`.
37void functionTyped(List<void Function(String message)> listeners) {
38 for (final void Function(String message) listener in listeners) {

Valid

example.dartdart
final int topLevel = 1;

class Holder {
  final int value;
  static final Holder empty = Holder(0);

  Holder(this.value);
}

void params(int x, {String? name}) {
  var y = x + 1;
  int z = y;
  const w = 3;
  print('$z$name$w');
}

void loops(List<int> numbers, List<(int, int)> rows) {
  for (var n in numbers) {
    print(n);
  }
  for (var (a, b) in rows) {
    print(a + b);
  }
  var (c, d) = rows.first;
  print(c + d);
  for (final int i = 0; i < 1;) {
    print(i);
    break;
  }
}

void cases(Object o) {
  if (o case int value) {
    print(value);
  }
  switch (o) {
    case var other:
      print(other);
  }
}

// Collection `for` elements are not `for` statements; the analyzer skips them.
List<int> elements(List<int> numbers, List<(int, int)> rows) => [
  for (final n in numbers) n,
  for (final int m in numbers) m,
  for (final (a, b) in rows) a + b,
];

Configure unnecessary-final

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "unnecessary-final": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/unnecessary-final: <reason>