Dart promised Sound null-safety to prevent us from committing the Billion Dollar Mistake. Unfortunately, neither Flutter nor our code is truly Soundly Null Safe.
Whenever you use the bang operator
! on a nullable variable, you tell the compiler that you know better than the compiler, and the variable will not be null.
To have a truly null-safe code, we should not use the Bang! operator and handle possible nulls in the code correctly.
If you first check if a field is non-null then the compiler should detect that and not warn anymore about possible null safety, right? In dart it is not the case:
Final fields in dart are not really final — Dart allows developers to override them:
We are creating
A class that has a final field.
B that inherits it, we are allowed to override the final field as a getter — this is the biggest problem why final fields in Dart are not really ever final.
Moreover, the following code will throw even though we checked for
One of the solutions for the compiler to work for you instead of against you is to assign properties to the local final (1).
In that code, we are assigning the field to a local final variable that can never change.
The positive side of this solution is that the compiler will work for you and not against you.
The negative side is that you will need to make a copy of every non-nullable field in your class.
If you are willing to add a couple of additional lines to your Widget classes, then you will be able to safely remove those pesky Bang! operators.
If this solution is too verbose for you, continue using Unit Tests and hopefully in the future Dart will change final fields to be really final.
1. This is the way how developers handle non-final fields in a multithreaded environment as well.