The 6 new lints in Dart 3.0

Alexey Inkin
Flutter Senior
Published in
3 min readJun 3, 2023

Dart 3 was released a few weeks ago. The announcement explains major features but does not tell you about the new lints, so let’s go into them.

deprecated_member_use_from_same_package

There is an analytics diagnostic message deprecated_member_use that used to flag all uses. However, in your libraries you frequently need to deprecate something for external use while still using it in the library itself. Before 3.0 you had to ignore those warnings. Now that diagnostic message is no longer triggered if you use a deprecated member in the same library, and the new lint was added. If you do not enable it manually, the analyzer will just stay silent on the issue.

invalid_case_patterns

With the new semantics of switch added, some older valid case expressions will become invalid or change their meaning. Most likely you have never used any of that, and it is fascinating to learn what was possible before (from the new lint’s doc):

switch (obj) {
case {1}: // Set literal.
case (1): // Parenthesized expression.
case identical(1, 2): // `identical()` call.
case -pi: // Unary operator.
case 1 + 2: // Binary operator.
case true ? 1 : 2: // Conditional operator.
case 'hi'.length: // .length call.
case i is int: // is expression.
}

This lint allows you to flag those cases while you are migrating to 3.0.

type_literal_in_constant_pattern

This code was valid before Dart 3.0 and is still valid in the new version:

switch (obj) {
case int:
}

It checks if obj is of type Type and represents the int type. However, with the new patterns in Dart 3.0, people will be testing for variable types using switch a lot, and some may write the above code hoping that it will do the type test matching just any int variable.

To prevent this confusion, the above syntax now triggers a lint, and you are forced to choose the more explicit syntax:

switch (obj) {
case int _: // obj being any int variable.
case == int: // obj being of type Type and representing the int type.
}

The team had a great detailed discussion here if you want more.

unnecessary_breaks

Before Dart 3.0, the break statement was required in this code:

switch (a) {
case 1:
print(1);
break;
case 2:
print(2):
}

There was no way to omit it, because Dart did not support falling through one case into another. The break statement at the normal end of a case was required only for clarity for those coming from the C language.

With the Dart 3.0, the team has decided to drop this requirement, so the link was added to flag break statements that do nothing.

You can still use break to exit a case earlier:

switch (a) {
case 1:
if (!shouldPrint) break;
print(1);
}

matching_super_parameters

This code can lead to errors:

class Shape {
double width;
double height;

Shape(this.width, this.height);
}

class Rectangle extends Shape {
Rectangle(super.height, super.width);
}

Note that width and height go in a changed order in the constructor of the subclass. The new lint flags such accidents.

no_literal_bool_comparisons

This is too verbose:

void fn(bool b) {
if (b == true) {
// ...
}
}

This should just be written as:

void fn(bool b) {
if (b) { // Dropped '== true'
// ...
}
}

This was in the Effective Dart long ago, but only now a lint was introduced for that.

The linter version confusion

The documentation for the last two lints claims they are not released and does not show the linter version where they are first available. However, with my Dart 3.0.2 SDK I have used them successfully. If they do not work for you, please let me know in a comment.

The Earlier Lints

If you have missed my articles on older lints, read them now:

Enabling the New Lints

Read this article on how to enable those new lints manually.

Alternatively, you can use my package total_lints which enables most of the lints for your project. I use it to avoid repeating the linter configuration for my projects.

--

--

Alexey Inkin
Flutter Senior

Google Developer Expert in Flutter. PHP, SQL, TS, Java, C++, professionally since 2003. Open for consulting & dev with my team. Telegram channel: @ainkin_com