Checking, if optional parameter is provided in Dart

The feature existed at some point in Dart's development, but it was removed again because it caused more complication than it removed, without solving the problem that actually needed solving - forwarding of default parameters.

If you have a function foo([x = 42]) and you want a function to forward to it, bar([x]) => f(x);, then, since foo could actually tell if x is passed or not, you actually ended up writing bar([x]) => ?x ? foo(x) : foo();. That was worse than what you had to do without the ?: operator.

Ideas came up about having a bar([x]) => foo(?:x) or something which pased on x if it was present and not if it was absent (I no longer remember the actual proposed syntax), but that got complicated fast, fx converting named arguments to positional - bar({x,y}) => foo(?:x, ?:y); - what if y was provided and x was not. It was really just a bad solution for a self-inflicted problem.

So, the ?x feature was rolled back. All optional parameters have a default value which is passed if there is no matching argument in a call. If you want to forward an optional parameter, you need to know the default value of the function you are forwarding to.

For most function arguments, the declared default value is null, with an internal if (arg == null) arg = defaultValue; statement to fix it. That means that the null value can be forwarded directly without any confusion.

Some arguments have a non-null default value. It's mostly boolean arguments, but there are other cases too. I recommend using null for everything except named boolean parameters (because they are really meant to be named more than they are meant to be optional). At least unless there is a good reason not to - like ensuring that all subclasses will have the same default value for a method parameter (which may be a good reason, or not, and should be used judiciosuly).

If you have an optional parameter that can also accept null as a value ... consider whether it should really be optional, or if you just need a different function with one more argument. Or maybe you can introduce a different "missing argument" default value. Example:

abstract class C { foo([D something]); }
class _DMarker implements D { const _DMarker(); }
class _ActualC {
  foo([D something = const _DMarker()]) {
    if (something == const _DMarker()) {
      // No argument passed, because user cannot create a _DMarker.
    } else {
      // Argument passed, may be null.
    }
  }
}

This is a big workaround, and hardly ever worth it. In general, just use null as default value, it's simpler.


I was trying something similar:

This does not work

widget.optionalStringParameter ? widget.optionalStringParameter : 'default string'

This works

widget.optionalStringParameter != null ? widget.optionalStringParameter : 'default string'

This also works

widget.optionalStringParameter ?? 'default string'