Issue
In the code below, I’m casting away the nullability by using the bang operator.
void main() {
String? foo;
foo!.toLowerCase();
}
But when I use assert
just before calling the function, I get an error.
void main() {
String? foo;
assert(foo != null);
foo.toLowerCase(); // Error
}
Is bang operator not doing the same thing behind the scene?
Note: I’m not looking for a solution to how to make it work, there are many ways, even the flow statement ones, if (foo == null) return;
Solution
(Adding this an answer instead of a comment.)
The point of assert
s is that they can be disabled and that they will not incur any runtime penalty. It’s been some matter of debate, but the current philosophy is that this means that assert
s will not perform type promotion, so even if you do:
bool foo(Object object) {
assert(object is String);
// error: The getter 'isEmpty' isn't defined for the type 'Object'
return object.isEmpty;
}
For the same reason, assert(someLocalVariable != null)
will not promote someLocalVariable
to a non-nullable type:
bool bar(String? string) {
assert(string != null);
// error: The property 'isEmpty' can't be unconditionally accessed
// because the receiver can be null.
return string.isEmpty;
}
As of Dart 2.12 with null-safety enabled, however, you can get the desired effect by just performing the cast directly. That will promote the type and throw a runtime exception if the cast fails:
bool foo(Object object) {
object as String;
return object.isEmpty;
}
bool bar(String? string) {
string!;
return string.isEmpty;
}
Answered By – jamesdlin
Answer Checked By – Mary Flores (FlutterFixes Volunteer)