4 Ways to Avoid The Null Check (!) Operator On Flutter

Mario Gunawan
4 min readMar 16, 2023

The null check operator is an operator to tell our compiler that the nullable variable (a variable that could be null) is in fact, not null. It is done by putting an exclamation mark after the variable. For example, the code below will produce an error without the (!):

String getString() {
final String? nullableString = null;

return nullableString!;
}

This is basically saying “trust me, it’s safe!” to the compiler so the linter a.k.a the one evaluating errors in the code doesn’t complains that you return a nullable variable in a part of the code that should never be null (in the example above, returning a nullable string in a non-nullable function).

What if I tell you that it is not actually safe

Wow I did not know that before, thanks Sherlock!

But seriously, even though the purpose of this operator (!) is to ensure the compiler that we know what we are doing, there is a risk of human error, and it should always be avoided. This is the same argument as why we should avoid late variables in Dart. It is unsafe, and since it throws an error, it is one step away from inducing bugs in your code. There are several ways you can avoid using the null check keywords in your codes.

Strategy 1: Use the null coalescing (??) operator

This is an easy way to get you out of trouble. Basically, what the null coalescing operator do is checking the left part of the operation. If the left part is not null, use it, else, use the right part instead. The return nullableString ?? “” could be translated to:

if(nullableString != null) {
return nullableString;
}
else {
return "";
}

Strategy 2: Use optional chaining (?.) and Null coalescing (??)

The optional chaining operator is useful when you’re accessing an object that’s nullable. The code nullableString?.contains(“haha”) ?? false is equivalent to:

bool value = false;
if(nullableString != null) {
value = nullableString.contains("haha");
}

You can also use this operator to conditionally invoke an operation. For example, you have a nullable data fetcher from API, you can invoke:

dataFetcher?.getData();

instead of:

if(dataFetcher != null) {
dataFetcher.getData();
}

Strategy 3 : Use ternary operator (?)

If you are unfamiliar with the ternary operator, it is used as follows

condition ? valueIfTrue : valueIfFalse

Basically, we evaluate the condition beforehand to determine which value to be used. Be careful though, as using ternary operator for long methods tend to look messy, e.g.:

It’s hard to tell where second operation starts and where the first operation ends

That’s why, based on input from my senior, it’s better to just use a simple if-else statement for long ternary operations. Their rule of thumb is to use ternary operation if it’s one line and I kinda agree with it.

Strategy 4: Use Conditional Spreading (…?) for arrays

I just learned this today. Basically, we can conditionally spread a list. Spreading is copying all values from one list to another one. It’s useful for combining array like the above’s code suggests. One problem we might encounter is if the array is nullable, then we won’t be able to spread it without (!), at least that’s what I thought. Fortunately we have a conditional spreading where if the array is null, it won’t pass anything.

The code […?item1, …?item2] is equivalent with:

final list = [];
list.add(item1);
list.add(item2);

or, if you want to be fancy:

[]..add(item1)..add(item2);

That’s all. Thanks for reading!

--

--

Mario Gunawan

I'm a passionate mobile / web developer. Writing articles about software development, mainly about flutter and react.