
Ultimate Guide to Sound Null Safety in Flutter/Dart
What is Null Safety, and why and how to use it? Let’s get deep dive into Sound Null Safety, this time!
Before we get started I wanna say something!
I don’t know why some people hate Null Safety (It’s not unnecessary boilerplate or anything!) but this article may help to change their opinions, So please If there is anybody around you who think like that, send this article and help them enlighten!
As profound coders say;
Only suckers write code that sucks!
If we’re ready then let’s get started!
What is Sound Null Safety?
First of all!
Null is not evil but it’s not best friend either
Getting rid of null is not the goal. There’s nothing wrong with null.
The main goal is to prevent the unexpected null situations that lead us to problems! We’re just getting the null under control!
Why do we need it anyway?
The answer is simple! Not to make the billion-dollar mistake!
What is soundness?
It’s a jargon word in static programming analysis
Basically, ensures the program can’t get into certain invalid states.
The benefits of soundness
- Revealing type-related bugs at compile time. (runtime errors go to hell!)
- More readable, and maintainable code.
- Better AOT (Ahead of Time) compilation.
- We can declare our intent better. This leads to APIs that are self-documenting and easier to use.
- The compiler could optimize our code, and give us smaller and faster apps.
Now, Let’s take a look at the architecture a bit!

Before null safety, everything contains Null and that leads to every type of support being null by default and that’s the problem!

As you can see we detached Null and isolated it from the tree for the sake of null safety! In this way, nothing will depend on NullBy doing this we will prevent any unwanted null problem in our app.
Let’s see how Null Safety works in practice now!
String myString;bool isEmpty(String string) => string.length == 0;// Without null safety
// Crashes while user's is using the app!
isEmpty(myString);// With null safety
// The app can't even be compiled!
isEmpty(myString);
// So that we will ensure that null case handled properly
// and that will make our moms proud of us!Now, It makes sense, right?
Then let’s take a look at Null Aware Operators now!!
Null aware operators

? — I’m a union-type variable I can be both a defined variable and a Null
That Means: String = String and String? = String or Null

Some basic rules
- Unless we tell Dart that can be null, Dart will assume it’s non-nullable!
// WTH, bro? don't you see I only accept String values. Why you still trying me to set null!
String text;- If you don’t specify a value to a nullable variable then the default value will be
null
// I got it, bro! I'm null for now but you'll set me a value later
String? text;! — I promise, I won’t let pass any null here!
String? text;
String newText = text!; // you can't assign it to me! Because you and I, We're different worlds variables. If you want me to be with you, you have to get rid of your null habits!!. —If anyone is missing, the party will be canceled!
class User { Address? address; }
class Address {String? name; }user!.address!.name!
?. — If anyone is missing, the party is over!
class User { Address? address; }
class Address {String? name; }User? user;// the first one is equivalent to the second one!
// choose your side wisely!final name = user?.address?.name;final name = getNameOrNull();
String? getNameOrNull() {
if (user == null) {
return null;
} else {
if (user!.address == null) {
return null;
} else {
if (user!.address!.name == null) {
return null;
} else {
return user!.address!.name;
}
}
}
}?? — if Jack won’t attend the party just bring someone else!
String? jack;String yep = jack ?? 'someoneElse';??= — If your friend won’t join us then call ___ instead!
String? yourFriend;String kevin = 'kevin';
String martha = 'martha';yourFriend ??= kevin;
yourFriend ??= martha;print(yourFriend); // returns kevin
// because jack join the group and martha couldn't make it!late — I’ll be late so you can start the party without me. I’ll be joining you later!
late String ehe; // won't throw an error because it'll be initialized laterehe = 'yuppi';Note: If you declare a variable
lateand the variable is read before it’s assigned a value, an error is thrown.
Local variables are the most flexible case. A non-nullable local variable doesn’t need to have an initializer. This is perfectly fine:
// result will be act like, it has a late keyword!
int someMethod() {
int result;
result = 5;
return result;
}required — Optional parameter but also has to get a value!
// throws an error
// because you say it's optional can be null but also it's nullable!
void method({String value}){}// now it's better!
void method({required String value}){}We also can control the spreads, cascades, indexes, and keys!
// Null-aware spread operator
final newList = [...list, ...?list2];// Null-aware cascade operator
receiver?..method();
receiver!..method();// Null-aware index operator
receiver?[i];
receiver![i];// Null-aware key operator
map['key']?.name;
map['key']!.name;Flow Analysis of Dart!
Dart compiler is smart enough to analyze the code flow and reachability. So, even if you use return, break, or throw; there won’t be any problem at all!
Let’s take a look at a simple example step by step
// Compiler will warn you because you didn't return anything!!
int method(String? value) {
}// This time warn you because value can be null but you don't expect a null value!
int method(String? value) {
return value.length;
}// Dart will understand the value won't be null because It's checked before using
// and won't warn you for length issue but this time will warn you for unhandled return statement!
int method(String? value) {
if (value != null) return value.length; // ok
}// and we are perfect!
int method(String? value) {
if (value != null) return value.length;
return 0;
}As you can see Null Safety doesn’t give us any space to make any mistakes!
That makes the app much more reliable and safe!
Lastly
You may say, why don’t you talk about Never?
Then I’ll say we’ll need that almost NEVER! So why bother?
BTW, If you haven’t migrated your project yet, click on the following link!
Thanks to Paul Allard. he prepared a syntax quick reference in DartPad. You should check this out, too!
Also, I highly recommend this article to you to comprehend the theory!
References
You can think of this article as a simplified version of the official one!
Thank you for reading!
I tried to create examples as simple as possible. Hope you like it.
If you liked this article, click on the 👏 button (did you know you could go up to 50?)
