Incorrectly assigning a variable of custom type does not give an error in static type check

Viewed 64

I am assigning a variable stringFn of type Function(String) like :

Function(String) stringFn = (String? s) {};

The dart static type checking does not give an error even though the stringFn is assigned a function that can receive a nullable parameter.

Printing the runtimeType of stringFn results in (String?) => Null but if I call the function :

stringFn(null);

results in The argument type 'Null' can't be assigned to the parameter type 'String' which I agree because the type does not allow nullable parameter.

Am I missing something here ?

1 Answers

This is intended behavior. String? can be thought of as a more generic type than String because it can accept all Strings and null.

Therefore, any String passed to a Function(String) can be guaranteed to be handled properly by your (String? s){}. stringFn claims it can handle all non-null String values based on its variable type. (String? s){} knows how to handle all of those non-null Strings in addition to null, so the code is valid.

You'll see that if you try to pass null to stringFn, you should get a static analysis error, not runtime:

void main() {
  Function(String) stringFn = (String? s) {};
  
  stringFn(null);//The argument type 'Null' can't be assigned to the parameter type 'String'
}

Attempting to do the reverse(flip the type and the assignment) will show a static analysis error on the stringFn line:

void main() {
  Function(String?) stringFn = (String s) {};//The argument type 'Null Function(String)' can't be assigned to the parameter type 'dynamic Function(String?)'
  
  stringFn(null);
}

This is again expected as your argument (String s){} does not know how to handle a nullable type as your variable's type implies it should. Based on the type of stringFn, null should be handled properly, but it wouldn't be able to do so with (String s){}.

Related