Checking for null on class member will not infer type as non-nullable

I’ve put together an example which explains my issue in more detail:
https://nullsafety.dartpad.dev/6de875a40e252fe38f3273c30edcb725

Normally something like this works:

String? prop;
final list = [
  if (prop != null)
    generateString(prop),
];
print(list);

But not if the property is a class member:

Example example = Example();
final list = [
  if (example.prop != null)
    generateString(example.prop),
];
print(list);

class Example {
  String? prop;
}

Here the compiler still complains that the property can be null:

Error: The argument type 'String?' can't be assigned to the parameter type 'String'.
      generateString(example.prop),
                             ^

1 possible answer(s) on “Checking for null on class member will not infer type as non-nullable

  1. Correct. Dart does not do type promotion on instance variables.

    Promotion only applies when the compiler can guarantee that the value you check is the same value you later use, and it is only based on local analysis of the code in the same function. If something can change the value of a variable between the two points, it’s not unsafe to promote the variable.

    In this case, your example could fail if the Example class changed to have a prop getter which returned different values. That would be silly, but the compiler only cares about guaranteed correctness, not just being safe for non-silly code.
    The promotion doesn’t depend on the implementation of Example, only its interface, so even though this program would be safe, the static promotion analysis can’t see that.

    (Dart also doesn’t promote static or top-level variables because it cannot know that you won’t run code writing to them. Type promotion only works for local variables, because that’s the only variables that a function-body local analysis can safely reason about.)

    In this case, I’d do:

    var prop = example.prop;
    var list = [if (prop != null) generateString(prop)];