In nullsafety.dartpad.dev if I write the following code:
void main() {
String? name = 'Bob';
print(name.length);
}
I get the following compile-time error:
An expression whose value can be 'null' must be null-checked before it can be dereferenced
And the following runtime error:
Property 'length' cannot be accessed on 'String?' because it is potentially null.
The Type promotion on null checks documentation says:
The language is also smarter about what kinds of expressions cause promotion. An explicit
== null
or!= null
of course works. But explicit casts usingas
, or assignments, or the postfix!
operator we’ll get to soon also cause promotion. The general goal is that if the code is dynamically correct and it’s reasonable to figure that out statically, the analysis should be clever enough to do so.
There is no possible way name
could be null in the code above. The documentation also says assignments should cause type promotion. Am I misunderstanding type promotion or is this a bug in DartPad?
Since a couple of the answers are providing workaround solutions to the error messages, I should clarify that I'm not trying to solve the coding problem above. Rather, I'm saying that I think the code should work as it it. But it doesn't. Why not?
Null safety prevents errors that result from unintentional access of variables set to null . For example, if a method expects an integer but receives null , your app causes a runtime error. This type of error, a null dereference error, can be difficult to debug.
Principles of null safetyWithout explicit nullability declarations, variables in the Dart programming language cannot be null. It is entirely up to you to make the switch to null safety. You can decide when and what to move to null safety. The same project can have null-safe and non-null-safe code stages.
Null safety leads to fewer bugs, smaller binaries, and faster execution once your entire project and its dependencies are migrated to null safety.
This answer is in response to the bounty that was added to the original question. The bounty reads:
Please explain how
String?
is different fromString
and how type promotion works in Dart.
The type String?
can contain a string or null
. Here are some examples:
String? string1 = 'Hello world';
String? string2 = 'I ❤️ Dart';
String? string3 = '';
String? string4 = null;
The type String, on the other hand, can only contains strings (once null safety is a part of Dart, that is). It can't contain null
. Here are some examples:
String string1 = 'Hello world';
String string2 = 'I ❤️ Dart';
String string3 = '';
If you try to do the following:
String string4 = null;
You'll get the compile-time error:
A value of type 'Null' can't be assigned to a variable of type 'String'.
The String
type can't be null
any more than it could be an int
like 3
or a bool
like true
. This is what null safety is all about. If you have a variable whose type is String
, you are guaranteed that the variable will never be null
.
If the compiler can logically determine that a nullable type (like String?
) will never be null
, then it converts (or promotes) the type to its non-nullable counterpart (like String
).
Here is an example where this is true:
void printNameLength(String? name) {
if (name == null) {
return;
}
print(name.length);
}
Although the parameter name
is nullable, if it actually is null
then the function returns early. By the time you get to name.length
, the compiler knows for certain that name
cannot be null
. So the compiler promotes name from String?
to String
. The expression name.length
will never cause a crash.
A similar example is here:
String? name;
name = 'Bob';
print(name.length);
Although name
is nullable here, too, the string literal 'Bob'
is obviously non-null. This also causes name
to be promoted to a non-nullable String
.
The original question was regarding the following:
String? name = 'Bob';
print(name.length);
It seems that this should also promote name to a non-nullable String
, but it didn't. As @lrn (a Google engineer) pointed out in the comments, though, this is a bug and when null safety comes out, this will also work like the previous example. That is, name
will be promoted to a non-nullable String
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With