Don't execute assignment if value is null

Viewed 252

I am still coming up to speed with dart and wanted to know if there was an easier way to not execute a statement if the value is null. See example below:

I can always do the if statements below for setting field3 and field4, but felt like something like field5 should work. But when I try to do that, it complains that a null check operator is used on a null value.

Also I don't want to change the Map to have a dynamic value.

Is there a single one liner to do what I am trying to do, or do I just need to check for null before setting the value.

  Map<String, Object> myMap = {};

  print('running now');
  try {
    myMap['field1'] = DummyClass.getString('hello');
    myMap['field2'] = DummyClass.getString('good');

    //Is there a more concise way to do this than the 2 options below?

    if (DummyClass.getOptionalString('goodbye') != null) {
      myMap['field3'] = DummyClass.getOptionalString('goodbye')!;
    }

    String? temp = DummyClass.getOptionalString('go');
    if (temp != null) {
      myMap['field4'] = temp;
    }

    // This gives an error 'null check operator used on a null value'
    // myMap['field5'] ??= DummyClass.getOptionalString('to')!;

  } catch (e) {
    print('error condition, $e');
  }

  print(myMap);
}

class DummyClass {

  static String getString(String? strParam) {
    String? retString = getOptionalString(strParam);
    if (retString == null) {
      throw ('nulls are not allowed');
    }
    return retString;
  }

  static String? getOptionalString(String? strParam) {
    if (strParam == null || strParam.length < 3) {
      return null;
    }
    return strParam;
  }
}
3 Answers

The issue is that the ??= operator assigns to the left if it is null. Expanded, it would look something like this:

a ??= b;

// Equivalent to:

if (a == null) {
  a = b;
}

Which is not something that you're trying to achieve. AFAIK, there is no such operator yet in Dart. However, you can try this:

final possiblyNullValue = '';
final myMap = <String, String>{};

myMap['key'] = possiblyNullValue ?? myMap['key'];

// Equivalent to:

if (possiblyNullValue != null) {
  myMap['key'] = possiblyNullValue;
}

// or:

myMap['key'] = possiblyNullValue != null? possiblyNullValue : myMap['key'];

Which would work in your case as a one-liner.

There's no built-in way to do what you want, but you could write a function (or extension method) to do it. For example:

extension MapTrySet<K, V> on Map<K, V> {
  void trySet(K key, V? value) {
    if (value != null) {
      this[key] = value;
    }
  }
}

and then you could do:

myMap.trySet('field3', DummyClass.getOptionalString('goodbye'));
myMap.trySet('field4', DummyClass.getOptionalString('go'));

Alternatively, if you really want to use normal Map syntax, you could create your own Map class that has a void operator []=(K key, V? value) override and does nothing when the value is null, but that probably would not be worth the effort.

You could create your map with all entries, even null, and then filter the null values out:

void main() {
  try {
    final myMap = <String, dynamic>{
      'field1': DummyClass.getString('hello'),
      'field2': DummyClass.getString('good'),
      'field3': DummyClass.getOptionalString('goodbye'),
      'field4': DummyClass.getOptionalString('go'),
    }..removeWhere((k, v) => v == null);
    print(myMap);
  } catch (e) {
    print('error condition, $e');
  }
}
Related