"The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety "The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety flutter flutter

"The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety


Dart engineer Erik Ernst says on GitHub:

Type promotion is only applicable to local variables. ... Promotion of an instance variable is not sound, because it could be overridden by a getter that runs a computation and returns a different object each time it is invoked. Cf. dart-lang/language#1188 for discussions about a mechanism which is similar to type promotion but based on dynamic checks, with some links to related discussions.

So local type promotion works:

  String myMethod(String? myString) {    if (myString == null) {      return '';    }        return myString;  }

But instance variables don't promote. For that you need to manually tell Dart that you are sure that the instance variable isn't null in this case by using the ! operator:

class MyClass {  String? _myString;    String myMethod() {    if (_myString == null) {      return '';    }        return _myString!;  }}


The Error:

Let's say, this is your code and you're doing a null check on the instance variable and still seeing an error:

class Foo {  int? i = 0;  double bar() {    if (i != null) return i.toDouble(); // <-- Error    return -1;  }}

The method 'toDouble' can't be unconditionally invoked because the receiver can be 'null'.

The error you see in code like this is because Getters are not promoted to their non-nullable counterparts. Let's talk about the reason why.


Reason of the Error:

Let's say, there's a class Bar which extends Foo and override i variable and doesn't assign it any value (keeping it null):

class Bar extends Foo {  @override  int? i;}

So, if you could do

print(Bar().d() * 2);

You would have run into a runtime null error, which is why getters type promotion is prohibited.


Solutions:

We need to cast away nullability from int?. There are generally 3 ways to do this (more ways include the use of as, is, etc)

  • Use local variable (Recommended)

    double bar() {  var i = this.i; // <-- Use of local variable.  if (i != null) return i.toDouble();  return -1;}
  • Use ?. with ??

    double bar() {  return i?.toDouble() ?? -1; // Provide some default value.}
  • Use Bang operator (!)

    You should only use this solution when you're 100% sure that the variable (i) will never be null.

    double bar() {  return i!.toDouble(); // <-- Bang operator in play.}


Use Ternary Operator to fix errors like this. This is an example where headline1 can be null

                    Theme                        .of(context)                        .textTheme                        .headline1?.fontSize?? 32,