Rules / Style / prefer-final-fields

prefer-final-fields

lint/style/prefer-final-fields
recommended
Same as prefer_final_fields · Dart lints

Flags a private field that is initialized but never reassigned, so it could be final.

Marking such fields final documents that they never change after construction and lets the compiler enforce it, preventing accidental mutation. The analysis is deliberately conservative to avoid false positives: a whole-file scan first records every name that is ever assigned, compound assigned, or incremented, and any such write disqualifies that name (matched by identifier, so a like-named field in another class also protects it). A candidate is reported only when it is provably initialized through exactly one safe channel — a declaration initializer with no constructor ever touching it, or no initializer but every non-redirecting generative constructor setting it via : _x = ... or a this._x formal. Only private (underscore-prefixed) fields are considered, and those already final, const, late, external, or abstract are skipped.

Invalid

example.dartdart
// Private fields only ever initialized, never reassigned.
class A {
  int _a = 1;
  int get a => _a;
}

class B {
  static int _shared = 0;
  static int read() => _shared;
}

class C {
  int _c;
  C(this._c);
}

class D {
  int _d;
  D(int v) : _d = v;
}

class E {
  String _e = 'x';
  String describe() => _e;
}

class F {
  final List<int> items = [];
  int _f;
  F(this._f);
}
The private field '_a' could be 'final'.
2class A {
3 int _a = 1;
The private field '_shared' could be 'final'.
7class B {
8 static int _shared = 0;
The private field '_c' could be 'final'.
12class C {
13 int _c;
The private field '_d' could be 'final'.
17class D {
18 int _d;
The private field '_e' could be 'final'.
22class E {
23 String _e = 'x';
The private field '_f' could be 'final'.
28 final List<int> items = [];
29 int _f;

Valid

example.dartdart
// Fields that are reassigned, already final, public, or late.
class A {
  int _a = 0;
  void inc() {
    _a += 1;
  }
}

class B {
  int _b = 0;
  void assign(int v) {
    _b = v;
  }
}

class C {
  final int _c;
  C(this._c);
}

class D {
  int value = 0;
  void bump() {
    value++;
  }
}

class E {
  late int _e;
  void init() {
    _e = 5;
  }
}

class F {
  int _f = 0;
  void tick() {
    _f++;
  }
}

How to configure

Set the severity of prefer-final-fields in your falcon.json:

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