如何在 List<T> 中创建泛型函数以在 Dart 中获取非可选类型 - Null Safety

How to make a generic functions in List<T> to get a Non-Optional type in Dart - Null Safety

我们正在将我们的 Flutter 应用程序迁移到 null safety 中,我遇到了一堆缺失的帮手以便轻松摆脱一个 optional 变成一个相同类型的 non-optional。

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

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

并且类似于Swift中的compactMap(),我想要一个函数,可以将任何映射转换为排除空项且仅包含return列表的映射非可选项目 例如:

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();
  }
}


即使这确实删除了空值并执行了映射,它始终 return 列表中的可选类型相同,这意味着它不会解包并且 removeNulls() return 是 List<dynamic> 而不是 List<the_type_I_used>

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

改变这个:

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

至此

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

您可以轻松地将 List<T?> 折叠为 List<T>,并使用 Iterable.whereType<T>():

过滤掉 null 个元素
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> 使用独立于 TT 再次使 removeNulls 通用 来自 ListNullSafetyExtension。不要那样做。

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