flutterdartstatic-typing

Avoid duplication of null type checking in Dart


My current goal is to remove this code duplication:

final int? myNullableInt = 10;

/// Everywhere I need to do this null verification:
if (myNullableInt == null) return null;

return someOtherMethodThatReceivesANonNullableInt(myNullableInt);

I want to convert to something like we have in Kotlin:

final int? myNullableInt = 10;

return myNullableInt?.apply((myInt) => someOtherMethodThatReceivesANonNullableInt(myInt));

I did it:

extension ApplyIfNotNull on Object? {
  T? apply<T extends Object?>(Object? obj, T? Function(Object) fn) {
    if (obj == null) return null;
    return fn(obj);
  }
}

But this gives me a static error:

The argument type 'Object' can't be assigned to the parameter type 'int'.

Note: this should work with all types, e.g ints, Strings, double and MyOwnClassTypes.

Is there something I can do? or am I missing something?


Solution

  • extension ApplyIfNotNull on Object? {
      T? apply<T extends Object?>(Object? obj, T? Function(Object) fn) {
        if (obj == null) return null;
        return fn(obj);
      }
    }
    

    That doesn't work because it declares that the callback be capable of accepting any Object argument, but you're presumably trying to use it with a function that accepts only an int argument. It's also unclear why you've made an extension method since it doesn't involve the receiver (this) at all.

    You need to make your function generic on the callback's argument type as well:

    R? applyIfNotNull<R, T>(T? obj, R Function(T) f) =>
        (obj == null) ? null : f(obj);
    

    (That's the same as what I suggested in https://github.com/dart-lang/language/issues/360#issuecomment-502423488 but with the arguments reversed.)

    Or, as an extension method, so that it can work on this instead of having the extra obj argument:

    extension ApplyIfNotNull<T> on T? {
      R? apply<R>(R Function(T) f) {
        // Local variable to allow automatic type promotion.  Also see:
        // <https://github.com/dart-lang/language/issues/1397>
        final self = this;
        return (self == null) ? null : f(self);
      }
    }
    

    Also see https://github.com/dart-lang/language/issues/360 for the existing language feature request and for some other suggested workarounds in the meantime.