omit-local-variable-types

Same as omit_local_variable_types in Dart lints

Group
Style
Path
lint/style/omit-local-variable-types
Default
Off, opt in
Origin
Dart lints
Rule
303 of 512

Flags local variable type annotations that repeat the initializer's type.

When a local's declared type is exactly the static type of its initializer, var or final says the same thing with less noise. The same applies to for loop variables, both for (int i = 0; ...) and for (String s in strings) when the iterable's element type matches. For-in checks require an interface-typed iterable; a type parameter's bound supplies iteration semantics but is not the iterable's own static type. Enum values lists are source-derived static members, so their indexing, method calls, and inferred for-in bindings participate without SDK sources. Annotations that change the type (num n = 1, int? x = 0, Object o = '') are kept, as are those that drive inference of a generic call (int x = parse() where parse<T>() returns T).

int count = items.length; // flagged
var count = items.length; // ok

falcon reports only when both types are fully known; unknown components and omitted type arguments are skipped. Explicit dynamic type arguments are known types and participate in the exact comparison. The initializer is inferred with the declared type as its context, as the analyzer does, so List<int> xs = [], Box<int> b = Box() and double d = c ? 0 : 1.5 are flagged, while a coerced integer literal (double d = 1) keeps its annotation. Diagnostic spans stop at the annotation's last token, excluding trailing trivia.

Invalid

example.dartdart
class Point {
  final int x;
  Point(this.x);
}

int length(String s) => s.length;

void f(int n, String s, List<int> items, Point p, bool flag) {
  int a = 1;
  String b = 'text';
  final String c = s;
  Point d = Point(1);
  int e = p.x;
  int g = length(s);
  bool h = n > 2;
  List<int> i = <int>[1];
  double j = 1.5, k = 2.5;
  List<int> q = [];
  Set<String> r = {};
  Map<String, int> t = {'a': 1};
  for (int m = 0; m < n; m++) {}
  for (int item in items) {}
  print([a, b, c, d, e, g, h, i, j, k, q, r, t, flag]);
}

T identity<T>(T value) => value;
class Box<T> {
  final T value;
  Box(this.value);
  U convert<U>(U value) => value;
}
void genericInferred(Box<String> receiver, int Function() callback) {
  int argument = identity(1);
  Box<int> instance = Box(1);
  Box<int> explicitNew = new Box(1);
  int method = receiver.convert(1);
  int functionValue = callback();
}

void objectBound<T extends Object>(T? p) {
  final T y = p!;
  print(y);
}
Remove the unnecessary type annotation from this local variable.
8void f(int n, String s, List<int> items, Point p, bool flag) {
9 int a = 1;
Remove the unnecessary type annotation from this local variable.
9 int a = 1;
10 String b = 'text';
Remove the unnecessary type annotation from this local variable.
10 String b = 'text';
11 final String c = s;
Remove the unnecessary type annotation from this local variable.
11 final String c = s;
12 Point d = Point(1);
Remove the unnecessary type annotation from this local variable.
12 Point d = Point(1);
13 int e = p.x;
Remove the unnecessary type annotation from this local variable.
13 int e = p.x;
14 int g = length(s);
Remove the unnecessary type annotation from this local variable.
14 int g = length(s);
15 bool h = n > 2;
Remove the unnecessary type annotation from this local variable.
15 bool h = n > 2;
16 List<int> i = <int>[1];
Remove the unnecessary type annotation from this local variable.
16 List<int> i = <int>[1];
17 double j = 1.5, k = 2.5;
Remove the unnecessary type annotation from this local variable.
17 double j = 1.5, k = 2.5;
18 List<int> q = [];
Remove the unnecessary type annotation from this local variable.
18 List<int> q = [];
19 Set<String> r = {};
Remove the unnecessary type annotation from this local variable.
19 Set<String> r = {};
20 Map<String, int> t = {'a': 1};
Remove the unnecessary type annotation from this local variable.
20 Map<String, int> t = {'a': 1};
21 for (int m = 0; m < n; m++) {}
Remove the unnecessary type annotation from this local variable.
21 for (int m = 0; m < n; m++) {}
22 for (int item in items) {}
Remove the unnecessary type annotation from this local variable.
33 int argument = identity(1);
34 Box<int> instance = Box(1);
Remove the unnecessary type annotation from this local variable.
34 Box<int> instance = Box(1);
35 Box<int> explicitNew = new Box(1);
Remove the unnecessary type annotation from this local variable.
35 Box<int> explicitNew = new Box(1);
36 int method = receiver.convert(1);
Remove the unnecessary type annotation from this local variable.
36 int method = receiver.convert(1);
37 int functionValue = callback();
Remove the unnecessary type annotation from this local variable.
40void objectBound<T extends Object>(T? p) {
41 final T y = p!;

Valid

example.dartdart
class Point {
  final int x;
  Point(this.x);
}

T make<T>() => throw UnimplementedError();

void f(int n, String s, List<int> items, dynamic dyn) {
  var a = 1;
  final b = 'text';
  num c = 1;
  double d = 1;
  int? e = n;
  Object f = s;
  int g = make();
  Iterable<int> h = [];
  List<int>? i = [];
  Set<int>? q = {};
  dynamic j = n;
  int k = dyn;
  int l = n, m = dyn;
  int o;
  o = 1;
  for (num item in items) {}
  for (var item in items) {}
  print([a, b, c, d, e, f, g, h, i, j, k, l, m, o, q]);
}

T identity<T>(T value) => value;
void genericReturnPolicy() {
  int argument = identity(1);
  T localIdentity<T>(T value) => value;
  int localArgument = localIdentity(1);
  print([argument, localArgument]);
}

Configure omit-local-variable-types

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "omit-local-variable-types": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/omit-local-variable-types: <reason>