You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart泛型扩展方法优化:实现超类型兼容并保留类型推断

实现支持超类型返回且保留类型推断的When扩展

核心需求是要一个通用的when扩展方法,既能在满足条件时返回原对象,不满足时返回其超类型对象,同时保留Dart的类型推断能力,不用为每个特定类型(比如Widget)单独写扩展。

原方案的问题

  • 第一个泛型扩展仅能返回原类型T,用在Widget场景时需要手动强制转换,操作繁琐;
  • 针对Widget编写的特定扩展虽解决了转换问题,但需要为每个需求类型重复编写,扩展性差;
  • 尝试的双泛型<R extends Object, T extends R>扩展会丢失类型推断,导致返回值默认是Object,无法调用子类方法,存在类型安全隐患。

解决方案:调整泛型参数设计

以下扩展方法可完美解决问题,既支持超类型返回,又能保留完整的类型推断:

extension When<T extends Object> on T {
  R? when<R>(
    bool Function(T self) predicate, {
    R Function(T self)? otherwise,
  }) {
    if (predicate(this)) {
      // 满足条件时返回原对象,T必然是R的子类型(由类型推断保证)
      return this as R;
    }
    return otherwise?.call(this);
  }
}

效果验证

用你给出的测试代码验证:

final variable = 1.when((self) => self.isEven, otherwise: (self) => self + 0.5)!;

此时variable的类型会被自动推断为num(int和double的最小上界),可直接调用num的所有方法(比如toInt()),不会出现类型安全警告。

再看Widget场景的使用示例:

Widget build(BuildContext context) {
  return const Text("Hello").when(
    (self) => self.data == "Hello",
    otherwise: (self) => const Icon(Icons.error),
  )!;
}

这里返回值会被推断为Widget,不需要任何强制转换,编译器会自动识别。

方案可行原因

  • 泛型参数R由调用上下文自动推断:Dart会根据otherwise的返回类型和原对象T的类型,自动计算出两者的最小上界作为R的类型;
  • 无需重复编写特定类型扩展:无论用在int、Widget还是其他类型上,这个单一扩展都能处理;
  • 类型安全有保障:只要otherwise返回的是T的超类型,this as R的转换就不会出错,编译器也会在编译阶段进行类型检查。

内容的提问来源于stack exchange,提问作者FMorschel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:52:45