Problem
I am currently learning Flutter and familiar with TS. While Flutter/Dart is known for being strongly-typed, I'm encountering difficulties trying to narrowing down my nullable types (which would be possible in TS).
Specifically, I used FutureBuilder and an async function to fetch data, and tried to build widgets based on those data. The data is List<{ path: String, ... }> for brevity. However, I cannot access snapshot.data:
My approach looks dumb. I looked up the docs and the closest solution I found to my problem is type promotion, but I believe this is not what I'm looking for.
Code
child: FutureBuilder(
future: _selectedImages,
builder: (context, snapshot) {
// error: dart(unchecked_use_of_nullable_value)
if (snapshot.hasData) {
log(snapshot.data[0].path);
}
// error: dart(unchecked_use_of_nullable_value)
if (snapshot.hasData && snapshot.data.isNotEmpty) {
log(snapshot.data[0].path);
}
// this works
if (snapshot.hasData) {
final tmp = snapshot.data?[0].path;
if (tmp != null) {
log(tmp);
}
}
},
),
Editted for @pskink
I believe I covered all the cases, why the errors still pop up, do you know why ?
// this works
// builder: ((context, snapshot) =>
// switch ((snapshot.connectionState, snapshot.data)) {
// // TODO: Handle this case.
// (ConnectionState.none, _) =>
// Text('null ${snapshot.data.toString()}'),
// (ConnectionState.waiting, _) => const Text('text'),
// (ConnectionState.active, _) => const Text('text'),
// (ConnectionState.done, null) => const Text('text'),
// (ConnectionState.done, final data?) => const Text('text'),
// }),
builder: (context, snapshot) {
switch ((snapshot.connectionState, snapshot.data)) {
case (ConnectionState.none, _):
return Text('null ${snapshot.data.toString()}');
case (ConnectionState.waiting, _):
return const Text('text');
case (ConnectionState.active, _):
return const Text('text');
case (ConnectionState.done, null):
return const Text('text');
case (ConnectionState.done, final data?):
return const Text('text');
// no error if have this
// default:
// return const Text('text');
}
}


snapshot.hasDataalready mean thatsnapshot.data != null. You can look at source code ofasync.dartfile:But unfortunately, Dart Analytic doesn't have enough smart to know about a param inside a class isn't null like that.
Dart can only promote local variables to null safety. The field
dataof an AsyncSnapshot object can theoretically return anything the next time you read it, so it can't be promoted based on checking that the value you read in one place is not null. Even if that data is final and cannot be setter but promoted, it means that the author can’t change that field in the future. So, promotion is only for local variables.If you want a quick fix then you can just put ! behind the data after you check
snapshot.hasDataand it will be fine:And below is some code I usually use with FutureBuilder: