Skip to main content

Don't be always late...

· 2 min read

In code reviews, I often see a construction like this:

enum Some { option1, option2 }

final someCondition = Some.option2;

void main() {
late final String x;

switch (someCondition) {
case Some.option1:
x = 'a';
break;
case Some.option2:
x = 'b';
break;
}

print(x);
}

Take a look at the line late final String x. At first glance, there's nothing wrong with it: we don't initialize x immediately, but at some point later, so late modifier seems to be a good fit here, right?

Wrong. Dart compiler is smart enough to understand that there's no way for x to be unitialized when it's called at print(x). So you can just omit late modifier:

enum Some { option1, option2 }

final someCondition = Some.option2;

void main() {
final String x;

switch (someCondition) {
case Some.option1:
x = 'a';
break;
case Some.option2:
x = 'b';
break;
}

print(x);
}

And it's not just about being concise. It actually guards you against making an error. Take a look at the following snippet:

enum Some { option1, option2 }

final someCondition = Some.option2;

void main() {
late final String x;

switch (someCondition) {
case Some.option1:
x = 'a';
break;
}

print(x);
}

Do you see an error here? We don't process all the possible cases and, since in our case, someCondition == Some.option2 we will get a runtime error:

Uncaught Error: LateInitializationError: Local 'x' has not been initialized.

What if we remove late modifier?

enum Some { option1, option2 }

final someCondition = Some.option2;

void main() {
final String x;

switch (someCondition) {
case Some.option1:
x = 'a';
break;
}

print(x);
}

Now, we can't even run the code, since we get a compile-time error:

Error: Final variable 'x' must be assigned before it can be used.
print(x);
^
Error: Compilation failed.

It can help you in other cases as well, such as if..else or try..catch blocks.

So pay attention to this small detail and stay safe!