考虑以下类:

@immutable
class Foo<T, R> {
  const Foo({
    required this.bar,
  });

  final R Function(T data) bar;

  Foo copyWith({
    R Function(T data)? bar,
  }) {
    return Foo(
      bar: bar ?? this.bar,
    );
  }
}

在上面的类中,行bar: bar ?? this.bar会导致诊断消息:

参数类型"R Value(T)"无法分配给参数 类型"动态函数(动态)".

应该如何为不可变的通用类中的通用函数字段实现copyWith方法?

推荐答案

您的问题是您的copyWith实现被声明为返回Foo,但这是Foo<dynamic, dynamic>的缩写. 然后,类型推断自上而下流向返回的表达式,导致Foo(bar: bar ?? this.bar)被推断为构造Foo<dynamic, dynamic>,而不是构造Foo<T, R>(否则这将从自下而上的类型推断发生).

因此,您应该修复返回类型:

  Foo<T, R> copyWith({
    R Function(T data)? bar,
  }) {
    return Foo(
      bar: bar ?? this.bar,
    );
  }

请注意,您可以通过以下操作强制自下而上的推理:

  // Probably not what you want!
  Foo copyWith({
    R Function(T data)? bar,
  }) {
    var copy = Foo(
      bar: bar ?? this.bar,
    );
    return copy;
  }

这也可以避免静态类型错误,但它最终会隐式地将Foo<T, R>转换为Foo<dynamic, dynamic>,这可能不是您想要的.

我强烈建议在analysis_options.yaml文件中启用strict-raw-types,以捕捉意外省略通用类型参数时隐式使用dynamic的情况.

Dart相关问答推荐

切换到可靠的零安全后简单分配中的可空性不匹配

在 Flutter 中将 Widget 放在 ListView 之上

如何从 Dart 中的映射中过滤空值

Mockito - 在空安全迁移后存根方法

如何在streambuilder中查询firestore文档并更新listview

如何在 ListView 中添加额外的底部间距?

Flutter-创建一个倒计时(countdown)小部件

如何平移和zoom 图像?

用 Dart 模式替换静态继承

Dart 后期初始化final变量

Dart:如何判断变量类型是否为字符串

Dart 中的抽象基类

Dart - 将自纪元以来的毫秒数(UNIX 时间戳)转换为人类可读的时间

Dart:Iterable 与 List,总是使用 Iterable?

Dart 是否支持函数式编程?

我应该如何在 Dart 中测试 Future?

`FutureOr` 的目的是什么?

在 Dart 中,你能不能从一个构造函数中调用另一个构造函数

如何从 Dart 中的列表中获取随机元素?

从函数返回多个值