0

我们正在将我们的Flutter应用程序迁移到null 安全性中,我遇到了一堆缺失的帮助程序,以便轻松地将可选项转换为相同类型的非可选项。

为了让您了解上下文,我想要一个

List<String?> optionalList = ['hi', 'hola', null];

compactMap()Swift 类似,我想要一个函数,可以将任何地图转换为排除空项目的地图,并且只返回非可选项目的列表,例如:

final List<String> newNonOptionalList = optionalList.compactMap((item) => item.toUpperCase());
// newNonOptionalList = ['HI', 'HOLA']

我正在尝试为此类案例提供帮助,包括我认为对Dart有价值的许多其他案例。

有谁知道它为什么不起作用,这是我迄今为止尝试过的一点:

extension ListNullSafetyExtension<T> on List<T?>? {

Iterable<R> compactMap<R>(R Function(T element) convert) sync* {
  for (var element in this.removeNulls()) {
    if (element != null) yield convert(element);
  }
}

  List<T> removeNulls() {
    if (this == null) return [];
    this!.removeWhere((value) => (value == null));
    return List.from(this!).whereType<T>().toList();
  }
}


尽管这确实删除了空值并执行了映射,但它始终在列表中返回相同的可选类型,这意味着它不会解包并removeNulls()返回 aList<dynamic>而不是 aList<the_type_I_used>

我非常感谢您帮助理解为什么这两个函数永远不会改变它们的类型,因为我只能找到该主题的非常基本的泛型帖子。

4

2 回答 2

0

您可以使用以下方法轻松地将 a 折叠List<T?>为 a过滤掉的List<T>元素:nullIterable.whereType<T>()

List<String?> optionalList = ['hi', 'hola', null];
List<String> newNonOptionalList = optionalList.whereType<String>().toList();

如果您真的想要自己的扩展方法(即使它不会增加太多):

extension IterableNullSafetyExtension<T> on Iterable<T?>? {
  Iterable<T> removeNulls() => this?.whereType<T>() ?? [];
}

此外,您尝试实现的一件事是它ListNullSafetyExtension<T>已经是通用的并且在T. 当您稍后尝试添加扩展方法时:

List<T> removeNulls<T>() {

最后的额外内容再次<T>成为removeNulls通用的,使用独立于from的 a 。不要那样做。TTListNullSafetyExtension

另请参阅:如何在空安全 Dart 中将 List<String?> 转换为 List?堆栈溢出

于 2021-10-06T01:06:12.637 回答
0

改变这个:

final List<String> newNonOptionalList = optionalList.compactMap((item) => item.toUpperCase());

对此

final List<String> newNonOptionalList = optionalList.compactMap((item) => item.toUpperCase()).toList();
于 2021-10-06T00:31:04.817 回答